• django -- ORM实现出版社增删改查


    前戏

    我们来完成一个图书管理系统的增删改查

    表结构设计

    1. 出版社
      id   name
    2. 作者
      id  name
    3. 书
      id  title  出版社_id
    4. 作者_书_关系表
      id  书_id  作者_id

    创建表

    现在有个需求,当我们访问http://127.0.0.1:8080/press_list/这个网址时,django给我们返回所有的出版社名称,我们可以在models里创建一个press的类来生成数据表

    class Press(models.Model):
        id = models.AutoField(primary_key=True)  # id主键
        name = models.CharField(max_length=32)  # 出版社名称

    然后再Terminal里执行下面的两句代码:

    python manage.py makemigrations
    python manage.py migrate

    然后我们去往数据库里手动插入几条数据,添加好了之后我们该干什么了呢?想一想我上篇文章写的和上上篇文章写的,我们在浏览器访问上面的url是不是django先去url.py里去找这个路径,那我们就去url.py里添加一个

    url(r'^press_list/', views.press_list),

    添加好了,这个函数是不是还没有,那在去views里添加一个press_list的函数,记得导入这个类

    def press_list(request):
        ret = Press.objects.all()  # 查询所有的出版社
        print(ret)
        return HttpResponse('ok')

    结果

    <QuerySet [<Press: Press object>, <Press: Press object>, <Press: Press object>]>

    打印出来的是一个对象,大家在学面向对象的时候记不记得有个魔术方法__str__,通常用法是把对象的值打印出来,我们在去Press类里添加下面的代码

    # __str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
    
    class Foo(object):
    
        def __str__(self):
            return 'zouzou'
    
        def eat(self):
            print('we are eating...')
    
    obj = Foo()
    print(obj)
    
    结果:zouzou
    不会__str__方法的看这里
    class Press(models.Model):
        id = models.AutoField(primary_key=True)  # id主键
        name = models.CharField(max_length=32)  # 出版社名称
    
        def __str__(self):
            return self.name  

    注意:

    添加完__str__方法后不需要执行那两行命令,因为__str__方法对数据库没有影响

    然后我们重新访问一下刚才的网站,看一下ret的值

    <QuerySet [<Press: 清华出版社>, <Press: 北大出版社>, <Press: 复旦出版社>]>

    这样就打印出了我们的出版社名称,结合上篇的ret[0].name就可以取到第一个值

    print(ret[0].name)
    print(ret[1].name)
    print(ret[2].name)

    这样我们就取到了三个出版社的名称,现在出版社的名称取到了,我们要给返回一个press_list的页面,而不是一个ok,在来改一下press_list的函数

    def press_list(request):
        ret = Press.objects.all()  # 查询所有的出版社
    
        return render(request,'press_list.html',{'ret':ret})

    之前学了查询某个字段的值:

    User.objects.filter(email=ema,pwd=password)

    如果要查询所有的值用all

    User.objects.all()

    上面的{'ret':ret})在上篇里说过,是django的模版语言,上次是传了一个固定的值,这次我们是传了一个对象,里面暂时有三个值

    创建html文件

    函数有了,是不是差个press_list.html的文件,在去templates下新增一个press_list.html的文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <table border="1">
            <thead>
                <th>id</th>
                <th>名称</th>
            </thead>
            <tbody>
                {% for i in ret %}
                    <tr>
                        <td>{{ i.id}}</td>
                        <td>{{ i.name }}</td>
                    </tr>
                {% endfor %}
            </tbody>
    
        </table>
    
    </body>
    </html>
    press_list.html

    代码解释:

    {% for i in ret %}
          <tr>
             <td>{{ i.id}}</td>
             <td>{{ i.name }}</td>
         </tr>
    {% endfor %}

    这是django的模版语言里for循环的用法,之前我们是返回了一个值,用{{变量名}},现在我们是要取到所有的出版社,所以要用for循环,和python里的for循环一样,以{% for i in ret %}开始,以{% endfor %}结束,中间还是用{{变量名}}的方法取值

    现在我们都已经配置好了,在去访问一下网址看看效果

    我们在数据库里在加一条数据,也能展示在页面上,这样我们就完成了我们需要的功能

    用ORM往数据库里新增数据

    上面我们的数据都是我们手动在数据库里添加的,那怎么使用ORM往数据库里添加数据呢?使用

    User.objects.create(name=value)

    就可以往数据库里插入数据了,和上面的分析一样,先去url.py加上路由

    url(r'^add_press/', views.add_press),

    在去views里添加add_press函数

    # 添加出版社的处理函数
    def add_press(request):
        if request.method == 'POST':  # 表示用户要发数据
            name = request.POST.get('name')  # 获取用户填的出版社数据
            Press.objects.create(name=name)  # 将数据添加到数据库中
            return redirect('/press_list/')  # 跳转到出版社列表页面
        
        return render(request,'add_press.html')  # 表示获取页面

    在去创建一个新增数据的html文件叫add_press.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/add_press/" method="post">
            <input type="text" name="name">
            <input type="submit">
        </form>
    
    </body>
    </html>

    接下来我们访问http://127.0.0.1:8080/add_press/就可以实现在页面上往数据库里添加数据的功能了

    用ORM从数据库里删除数据

    我们已经完成了一个很low的往数据库里新增数据的功能,现在来完成一个删除的功能

    分析:

    删除数据我们根据什么来删,前面设计表的时候因为id是主键,所以我们可以根据id去删除数据,那么问题就来了,我们是不是要有一个删除的按钮。我们删除了数据之后,id是不是就不是按照顺序往上增加了,是不是要在前面加一个序号,删除之后序号也跟着改变呢。然后我们查询到数据,使用ORM里的方法删除数据

    表名.objects.filter('列名').delete()

    先去修改press_list.html的代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <a href="/add_press/">添加出版社</a>
        <table border="1">
            <thead>
                <th>序号</th>
                <th>id</th>
                <th>名称</th>
                <th>操作</th>
            </thead>
            <tbody>
                {% for i in ret %}
                    <tr>
                        <td >{{ forloop.counter }}</td>  <!--循环,从1开始,每次加1-->
                        <td>{{ i.id}}</td>
                        <td>{{ i.name }}</td>
                        <td><a href="/delete_press/?id={{ i.id}}">删除</a></td>
    
                    </tr>
                {% endfor %}
            </tbody>
    
        </table>
    
    </body>
    </html>

    代码解释:

    <td >{{ forloop.counter }}</td>  for循环,从1开始,如果想从0开始,则<td >{{ forloop.counter0 }}</td>
    <td><a href="/delete_press/?id={{ i.id}}">删除</a></td> 我们可以通过url访问,当点击删除的时候,浏览器会往服务器发送一个url地址:http://127.0.0.1:8080/delete_press/?id=XX的网址。

    然后我们去添加路由
    url(r'^delete_press/', views.delete_press),  # 删除出版社

    在去添加对应的函数

    # 删除出版社
    def delete_press(request):
        delete_id = request.GET.get('id')
        Press.objects.filter(id=delete_id).delete()
        return redirect('/press_list/')

    这样当我们点击删除时,会删除掉对应的数据,并且重新访问press_list网页

    Press.objects.filter(id=delete_id).delete()先查询数据,然后删除

    用ORM从数据库里更改数据

    先添加一个路由

    url(r'^edit_press/', views.edit_press),  # 编辑出版社

    这里有两种方法可以实现编辑

    第一种方法

    先去添加一个函数

    #编辑出版社
    def edit_press(request):
        if request.method=='POST':
            #取出用户点击编辑之后的数据
            edit_id = request.POST.get('id')
            new_name = request.POST.get('name')
            #去数据库修改对应的数据,先查询,在修改,在保存到数据库
            edit_press_obj = Press.objects.get(id=edit_id)
            edit_press_obj.name = new_name
            edit_press_obj.save()
            #让用户再次访问列表页面
            return redirect('/press_list/')
    
        #获取要编辑的出版社
        edit_id = request.GET.get('id')
        #获取该出版社的信息
        # ret = Press.objects.filter(id=edit_id)
        ret = Press.objects.get(id=edit_id)
        return render(request,'edit_press.html',{'press_obj':ret})

    代码解释:

    Press.objects.get(id=edit_id) 和filter都是查询数据的,不同的是get有且只能找到一个对象,否则会报错
    他们两个返回的值都是一个对象,filter取值是
    ret[0].name

    就能取出name的值,而get取值是

    ret.name

    在去添加一个edit_press.html的文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/edit_press/" method="post">
            <input type="text" name="id" value="{{ press_obj.id }}" style="display: none">
            <input type="text" name="name" value="{{ press_obj.name }}">
            <input type="submit" value="提交">
        </form>
    
    </body>
    </html>
    edit_press.html

    我们给服务器传了个id的值,把它设置了隐藏,这样服务器就能拿到我们的id值,才能去根据id唯一的修改数据

    第二种方法

    第二种方法和第一种差不多,我们在html文件里把id放到action里提交到服务器

    修改edit_press.html文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/edit_press/?id={{ press_obj.id }}" method="post">
            <input type="text" name="name" value="{{ press_obj.name }}">
            <input type="submit" value="提交">
        </form>
    
    </body>
    </html>
    edit_press.html

    不同的是我们把id的值放在了action里传给了服务器,然后服务器就可以通过GET方法得到id值

    修改edit_press函数

    #编辑出版社
    def edit_press(request):
        # 获取要编辑的出版社id,因为是在url里,所以用GET
        edit_id = request.GET.get('id')
    
        if request.method=='POST':
            #取出用户点击编辑之后的数据
            new_name = request.POST.get('name')
            #去数据库修改对应的数据,先查询,在修改,在保存到数据库
            edit_press_obj = Press.objects.get(id=edit_id)
            edit_press_obj.name = new_name
            edit_press_obj.save()
            #让用户再次访问列表页面
            return redirect('/press_list/')
    
        #获取该出版社的信息
        ret = Press.objects.filter(id=edit_id)[0]
        # ret = Press.objects.get(id=edit_id)
        return render(request,'edit_press.html',{'press_obj':ret})

    我们通过Press.objects.filter(id=edit_id)[0]获取到了值,如果使用的是Press.objects.get()就不需要再加[0],只有filter需要加[0]

    这样我们也实现了编辑的功能

    总结:

    ORM的语句

      查:  

        1. 类名.objects.all()       --> 返回一个列表
        2. 类名.objects.filter()    --> 返回一个列表,取值要用[0],如果是循环,就不需要加[0]
        3. 类名.objects.get()      --> 返回一个对象,必须只能有一个,否则会报错

      增:

        类名.objects.create(name='')       --> 创建一个对象,返回的就是刚创建的对象 

      删:

        类名.objects.filter(id=).delete()  --> 删除

      改:

        obj = 类名.objects.get(id='')

        obj.name = '新值' --> 修改对象的属性(修改数据行某个字段的值)

        obj.save() --> 把修改同步到数据库

    模版语言

    for循环
    {% for i in ret %}
      {{ i.属性 }}
      {{ forloop.counter }}     --> for循环从1开始计数
      {{ forloop.counter0 }}   --> for循环从0开始计数
    {% endfor %} 

  • 相关阅读:
    Hexo简介
    MarkDown基本语法
    Github 协同开发
    Java基础10:全面解读Java异常
    Java基础8:深入理解内部类
    Java基础9:解读Java回调机制
    Java基础6:代码块与代码加载顺序
    Java基础7:关于Java类和包的那些事
    java基础4:深入理解final关键字
    Java基础5:抽象类和接口
  • 原文地址:https://www.cnblogs.com/zouzou-busy/p/11135507.html
Copyright © 2020-2023  润新知