zoukankan      html  css  js  c++  java
  • python 全栈开发,Day71(模型层-单表操作)

    昨日内容回顾

    1. {% include '' %}
    2. extend
    
    base.html:
    
        </span>&lt;html&gt;<span style="color: #000000;">
            .....
            .....
            .....
            {</span>% block content%<span style="color: #000000;">}
            {</span>% endblock%<span style="color: #000000;">}
        </span>&lt;/html&gt;<span style="color: #000000;">
        
    index.html:
        {</span>% extend <span style="color: #800000;">'</span><span style="color: #800000;">base.html</span><span style="color: #800000;">'</span>%<span style="color: #000000;">}
        </span>&lt;p&gt;python&lt;/p&gt;<span style="color: #000000;">
        {</span>% block content%<span style="color: #000000;">}
        </span>&lt;p&gt;hello&lt;/p&gt;<span style="color: #000000;">
        {</span>% endblock%<span style="color: #000000;">} 
        
    子网页,也可以设置css和js。比如:
        {</span>% block css %<span style="color: #000000;">}
        {</span>% endblock %<span style="color: #000000;">}
        
        {</span>% block js %<span style="color: #000000;">}
        {</span>% endblock %<span style="color: #000000;">}
    

    models:ORM

     </span><span style="color: #0000ff;">class</span>          -----<span style="color: #000000;">    表
     属性变量       </span>-----<span style="color: #000000;">   字段名称
     属性值         </span>-----<span style="color: #000000;">   字段约束 
     
     对象           </span>------<span style="color: #000000;">  记录
    

    创建表的流程

    </span>1<span style="color: #000000;">. 在models里设计模型类
      </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Book(models.Model):
            nid</span>=models.AutoField(primary_key=<span style="color: #000000;">True)
            ...
    </span>2<span style="color: #000000;">. 更改数据库为mysql,在settings中:
        </span>2.1<span style="color: #000000;"> 先注册app
        INSTALLED_APPS </span>=<span style="color: #000000;"> [
        ...
        </span><span style="color: #800000;">'</span><span style="color: #800000;">app01</span><span style="color: #800000;">'</span><span style="color: #000000;">,
        ]
        </span>2.2<span style="color: #000000;"> 更改数据库引擎
        DATABASES </span>=<span style="color: #000000;"> {
            </span><span style="color: #800000;">'</span><span style="color: #800000;">default</span><span style="color: #800000;">'</span><span style="color: #000000;">: {
                </span><span style="color: #800000;">'</span><span style="color: #800000;">ENGINE</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">django.db.backends.mysql</span><span style="color: #800000;">'</span>,   <span style="color: #008000;">#</span><span style="color: #008000;"> 数据库引擎mysql</span>
                <span style="color: #800000;">'</span><span style="color: #800000;">NAME</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">book</span><span style="color: #800000;">'</span>,       <span style="color: #008000;">#</span><span style="color: #008000;"> 你要存储数据的库名,事先要创建之</span>
                <span style="color: #800000;">'</span><span style="color: #800000;">USER</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">root</span><span style="color: #800000;">'</span>,      <span style="color: #008000;">#</span><span style="color: #008000;"> 数据库用户名</span>
                <span style="color: #800000;">'</span><span style="color: #800000;">PASSWORD</span><span style="color: #800000;">'</span>: <span style="color: #800000;">''</span>,      <span style="color: #008000;">#</span><span style="color: #008000;"> 密码</span>
                <span style="color: #800000;">'</span><span style="color: #800000;">HOST</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">localhost</span><span style="color: #800000;">'</span>, <span style="color: #008000;">#</span><span style="color: #008000;"> 主机</span>
                <span style="color: #800000;">'</span><span style="color: #800000;">PORT</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">3306</span><span style="color: #800000;">'</span>,      <span style="color: #008000;">#</span><span style="color: #008000;"> 数据库使用的端口</span>
    

    }
    }

    </span>3<span style="color: #000000;">. 创建数据库book
    </span>4<span style="color: #000000;">. 必须安装2个模块
        pip3 install pymysql
        pip3 install mysqlclient
    
    </span>5<span style="color: #000000;">.
       python manage.py makemigrations(同步)
       python manage.py migrate(执行sql)</span></pre>
    
    View Code

    一、单表操作

    添加表纪录

    create(**kwargs) 建立新对象

    返回值是添加的model对象

    方式1 

    create方法的返回值book_obj就是插入book表中的python葵花宝典这本书籍纪录对象

    book_obj=Book.objects.create(title="python葵花宝典",state=True,price=100,publish="苹果出版社",pub_date="2012-12-12")

    方式2

    book_obj=Book(title="python葵花宝典",state=True,price=100,publish="苹果出版社",pub_date="2012-12-12")
    book_obj.save()

    举例:

    修改settings.py,打印orm转换过程中的sql。最后一行,添加如下内容:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }
    View Code

    修改urls.py,增加add路径

    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('add/', views.add),
    ]
    View Code

    models.py内容如下:

    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32, unique=True)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        pub_date = models.DateField()
        publish = models.CharField(max_length=32)
    View Code

    表已经生成了,但是表记录是空的。

    Pycharm有自带的工具,可以操作MySQL。点击右侧的Database

    点击加号-->Data Source-->MySQL

    这里提示要安装MySQL驱动,点击旁边的Download

     正在下载安装

     

    出现下面的效果,表示安装成功。

    点击测试连接,出现Successful,表示连接成功。

     双击展开,就可以看到app01_book表了。虽然models.py里面的类名是Book,但是实际创建的表名是应用名+models.py里面的类名。用下划线分割,大写字母会变成小写。

    修改views.py,增加add视图函数。

    注意,需要导入models模块

    这里面的title,price...变量是和Book类的属性是一一对应的,否则会报错。

    from django.shortcuts import render,HttpResponse
    from app01.models import Book
    # Create your views here.
    def add(request):
        book = Book(title="北京折叠",price="11.11",pub_date="2012-12-12",publish="苹果出版社")
        book.save()
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">添加成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    这是第一种方式:实例化一个对象,并传参。

    pub_date的值,必须是xxxx_xx_xx格式。用下划线分隔,其他符合是不可以的。

    访问网页,效果如下:

    双击右边的book表,查看表记录。点击刷新按钮,就可以看到数据了。

     注意:只要django执行了视图函数的那2句代码,就可以插入一条记录。

    并不一定,非要在views.py里面才行。具体放在哪里,是根据业务逻辑来处理。

    一般请求下,是放在views.py里面。

    查看控制台输出信息,会看到一条insert语句

    (0.001) INSERT INTO `app01_book` (`title`, `price`, `pub_date`, `publish`) VALUES ('北京折叠', '11.11', '2012-12-12', ' 苹果出版社'); args=['北京折叠', '11.11', '2012-12-12', '苹果出版社']

    那么book.save(),就是执行上面这句SQL,来插入一条记录的。

    第二种方式:推荐使用
    objects:表示管理器。
    Book.objects:表示管理book表。
    book.objects.create:表示增加操作。

    def add(request):
        book = Book.objects.create(title="放风筝的人", price="14.11", pub_date="2017-12-12", publish="苹果出版社")
        print(book)
        print(book.title)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">添加成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    这种方式,一行代码,就搞定了。

    create是有返回值的,create内部里面有save。


    访问add页面

    查看控制台

    (0.002) INSERT INTO `app01_book` (`title`, `price`, `pub_date`, `publish`) VALUES ('放风筝的人', '14.11', '2017-12-12', '苹果出版社'); args=['放风筝的人', '14.11', '2017-12-12', '苹果出版社']
    Book object (2)
    放风筝的人
    View Code

    create的返回值是一个类对象,比如:Book object

    book_obj.title的返回值,就是create里面的值。

    create执行的SQL和save是一样的。区别是create代码更精简!

    如果create少一个字段,比如price呢?测试一下

    def add(request):
        book_obj = Book.objects.create(title="放风筝的人2",pub_date="2018-12-12",publish="苹果出版社")
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">添加成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

     访问页面,提示price不允许为空

     

    更改models.py里面的price属性,设置价格属性为空

    添加字段is_pub,表示是否发布

    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32, unique=True)
        price = models.DecimalField(max_digits=8, decimal_places=2,null=True)
        pub_date = models.DateField()
        publish = models.CharField(max_length=32)
        is_pub = models.BooleanField()
    View Code

    Pycharm有一个工具,不同执行繁琐的同步命令

    Tools-->Run manage.py Task...

    输入ma,就会有提示信息。选择makemigrations,直接回车

     最后输出如下信息

    意思就是is_pub字段必须设置一个默认值

    重新修改models.py下的Book类,增加默认值

    is_pub = models.BooleanField(default=False)

    关闭下面的小窗口,重新运行命令makemigrations

     输出下面信息,表示成功了

    执行migrate

    查看表记录,发现多了一个is_pub字段。BooleanField对应的MySQL类型是tinyint(1)

    那么False对应的值是0,true对应的值是1。

    再次刷新页面,就可以了

    查看表记录,点击刷新按钮

     再次刷新页面,会报错!因为title字段是唯一的。

     

    修改views里面的add视图函数

    book_obj = Book.objects.create(title="放风筝的人3", pub_date="2018-12-12", publish="苹果出版社")

    再次刷新页面,就可以了。查看表记录,刷新一下

    注意:在开发项目时,最好打开日志,这样可以查看ORM转换的SQL语句,方便后面的调试。

    查询表纪录

    查询API

    <1> all():                  查询所有结果
    

    <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象

    <3> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,
    如果符合筛选条件的对象超过一个或者没有都会抛出错误。

    <4> exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象

    <5> order_by(*field): 对查询结果排序

    <6> reverse(): 对查询结果反向排序

    <8> count(): 返回数据库中匹配查询(QuerySet)的对象数量。

    <9> first(): 返回第一条记录

    <10> last(): 返回最后一条记录

    <11> exists(): 如果QuerySet包含数据,就返回True,否则返回False

    <12> values(field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
    model的实例化对象,而是一个可迭代的字典序列
    <13> values_list(
    field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

    <14> distinct(): 从返回结果中剔除重复纪录

    View Code

    all() 查询所有结果

    它返回的是QuerySet数据类型对象,它是django orm 特有的数据类型。

    数据格式为:[model对象1,model对象2,model对象3 ...]

    它和下面的 animal_list类似。先是一个列表,列表的元素是一个对象

    class Annimal(object):
            def __init__(self, name, age):
                self.name = name
                self.age = age
    
        </span><span style="color: #0000ff;">def</span><span style="color: #000000;"> call(self):
            </span><span style="color: #0000ff;">return</span> <span style="color: #800000;">"</span><span style="color: #800000;">汪汪汪</span><span style="color: #800000;">"</span><span style="color: #000000;">
    
    dog </span>= Annimal(<span style="color: #800000;">"</span><span style="color: #800000;">旺财</span><span style="color: #800000;">"</span>, 3<span style="color: #000000;">)
    cat </span>= Annimal(<span style="color: #800000;">"</span><span style="color: #800000;">小雪</span><span style="color: #800000;">"</span>, 4<span style="color: #000000;">)
    duck </span>= Annimal(<span style="color: #800000;">"</span><span style="color: #800000;">小黄</span><span style="color: #800000;">"</span>, 5<span style="color: #000000;">)
    
    animal_list </span>= [dog, cat, duck]</pre>
    
    View Code

    一个对象,就是一条记录。有多少条记录,就有多少个对象。

    举例:

    修改urls.py,增加query路径

    urlpatterns = [
        path('admin/', admin.site.urls),
        path('add/', views.add),
        path('query/', views.query),
    ]
    View Code

    修改views.py,增加query视图函数

    def query(request):
        ret = Book.objects.all()
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    访问页面,效果如下:

    查看控制台输出信息:

    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` LIMIT 21; args=()
    <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>, <Book: Book object (3)>, <Book: Book object (5)>]>
    View Code

    它执行的sql,就是select...。返回结果是一个QuerySet数据类型

    它是一个列表,里面放了多个对象。个数取决于返回的行数!

    QuerySet和model对象的区别:

    只有model对象,才能调用属性。
    queryset不能直接调用属性,因为它是一个列表。

    既然是列表,就可以使用for循环,打印title属性。

    修改query视图函数

    def query(request):
        book_list = Book.objects.all()
        print(book_list)
        for obj in book_list:
            print(obj.title)  # 打印title属性
    
    <span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台,就会有4个书名

    北京折叠
    放风筝的人
    放风筝的人2
    放风筝的人3
    View Code

    filter(**kwargs):  它包含了与所给筛选条件相匹配的对象

    filter可以用指定条件来查询,它会返回一条或者多条记录。

    它的返回值是QuerySet数据类型对象

    举例:查看标题为北京折叠的记录

    修改query视图函数

    def query(request):
        ret = Book.objects.filter(title='北京折叠')
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台信息

    (0.001) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`title` = '北京折叠' LIMIT 21; args=('北京折叠',)
    <QuerySet [<Book: Book object (1)>]>
    View Code

    它执行的sql,是用了where条件的。

    注意,下面这行代码,不能直接执行

    print(ret.price)

    刷新页面,报错。QuerySet不能直接调用属性,即使它只有一个对象

    虽然可以通过切片来调用属性,但是不推荐使用。
    因为它的长度是不固定的。

    需要使用for循环来执行。

    first(): 返回第一条记录

    first用来取一条记录,如果返回结果有多条,只会取第一条。

    它的返回结果是model对象。

    修改query视图函数

    def query(request):
        obj = Book.objects.all().first()
        print(obj)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` ORDER BY `app01_book`.`nid` ASC LIMIT 1; args=()
    Book object (1)
    北京折叠
    View Code

    查看sql,发现它使用order by排序。对主键nid,做了升序,并且使用limit 1返回一条结果。

    ret的返回结果一个是model对象,那么就可以直接调用对象了。所以输出:北京折叠

    学习API接口,重要的是它的返回值是什么

    last(): 返回最后一条记录

    last用来取最后一条记录,如果返回结果有多条,只会取最后一条。

    它的返回结果是model对象。可以直接调用属性!

    修改query视图函数

    def query(request):
        obj = Book.objects.all().last()
        print(obj)
        print(obj.title)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.002) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` ORDER BY `app01_book`.`nid` DESC LIMIT 1; args=()
    Book object (5)
    放风筝的人3
    View Code

    查看sql,发现它使用order by排序。对主键nid,做了降序,并且使用limit 1返回一条结果。

    所以最后输出:放风筝的人3

    还可以对all()进行切片操作

    def query(request):
        obj = Book.objects.all()[1:3]
        print(obj)
        for i in obj:
            print(i.title)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.001) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` LIMIT 2 OFFSET 1; args=()
    <QuerySet [<Book: Book object (2)>, <Book: Book object (3)>]>
    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` LIMIT 2 OFFSET 1; args=()
    放风筝的人
    放风筝的人2
    View Code

    [1:3],返回2条记录。切片原则:顾头不顾尾。

    get(**kwargs): 返回与所给筛选条件相匹配的对象

    返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

    它的返回结果是一个model对象。

    举例:查询nid为1的记录

    修改query视图函数

    def query(request):
        obj = Book.objects.get(nid=2)
        print(obj)
        print(obj.title)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.001) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`nid` = 2; args=(2,)
    Book object (2)
    放风筝的人
    View Code

    查看sql,发现它对应的where条件是nid = 2。返回结果的title属性为:放风筝的人

    举例:查询结果大于1时

    查看表记录,修改第3条记录的价格为14.11,并点击上面的提交按钮

    修改query视图函数,使用get查询价格等于14.11的记录。

    def query(request):
        obj = Book.objects.get(price=14.11)
        print(obj)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,报错!提示返回结果过多,不能大于2条。

    举例:查询结果大于1时,也就是记录不存在时

    修改query视图函数,查询价格等于110

    def query(request):
        obj = Book.objects.get(price=110)
        print(obj)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,报错!提示查询结果不存在

    下面的代码,也可以返回一条记录

    obj = Book.objects.filter(nid=2).first()

    但是使用first,它会执行order by。上面的代码转为SQL为:

     SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`nid` = 2 ORDER BY `app01_book`.`nid` ASC LIMIT 1;

    那么它的效果不如直接使用get!就一台记录,还排序干啥?

    总结:

    使用get有且只有一个结果时才有意义。

    推荐使用get时,利用主键查询,因为主键是唯一的。

    exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象

    exclude()用来做排除的,它的返回结果是QuerySet

    举例:查询价格不等于100的

    修改query视图函数

    def query(request):
        obj = Book.objects.exclude(price=100)
        print(obj)
        for i in obj:
            print(i.title,i.price)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>, <Book: Book object (3)>, <Book: Book object (5)>]>
    (0.001) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE NOT (`app01_book`.`price` = '100' AND `app01_book`.`price` IS NOT NULL); args=(Decimal('100'),)
    北京折叠 11.11
    放风筝的人 14.11
    放风筝的人2 14.11
    放风筝的人3 None
    View Code

    查看sql,发现它对应的where条件用了Not,返回结果是QuerySet

    order_by(*field): 对查询结果排序

    order_by,默认是升序,它的返回结果是QuerySet

    举例:查询所有书籍,按照价格排序

    修改表记录,效果如下:

    修改query视图函数

    def query(request):
        obj = Book.objects.order_by("price")
        print(obj)
        for i in obj:
            print(i.title,i.price)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    <QuerySet [<Book: Book object (5)>, <Book: Book object (1)>, <Book: Book object (2)>, <Book: Book object (3)>]>
    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` ORDER BY `app01_book`.`price` ASC; args=()
    水浒传 11.00
    北京折叠 11.11
    放风筝的人 14.11
    西游记 233.00
    View Code

    如果指定的字段值为空,则按照主键排序。

    每次for循环查看结果,太麻烦了。可以在models.py里面增加一个__str__方法。

    修改models.py,增加__str__方法,完整代码如下:

    from django.db import models
    

    # Create your models here.
    class Book(models.Model):
    nid
    = models.AutoField(primary_key=True)
    title
    = models.CharField(max_length=32, unique=True)
    price
    = models.DecimalField(max_digits=8, decimal_places=2,null=True)
    pub_date
    = models.DateField()
    publish
    = models.CharField(max_length=32)
    is_pub
    = models.BooleanField(default=False)

    </span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
        </span><span style="color: #0000ff;">return</span> <span style="color: #800000;">'</span><span style="color: #800000;">{}:{}</span><span style="color: #800000;">'</span>.format(self.title,self.price)</pre>
    
    View Code

    修改views.py下的query方法,代码如下:

    def query(request):
        obj = Book.objects.order_by("price")
        print(obj)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.001) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` ORDER BY `app01_book`.`price` ASC LIMIT 21; args=()
    <QuerySet [<Book: 水浒传:11.00>, <Book: 北京折叠:11.11>, <Book: 放风筝的人:14.11>, <Book: 西游记:233.00>]>
    View Code

    可以直接看到title和价格!

    注意:只有QuerySet数据类型对象,才能调用order_by

    reverse():  对查询结果反向排序

    它的返回结果是QuerySet

    举例:

    修改query方法

    def query(request):
        obj = Book.objects.all().order_by("price").reverse()
        print(obj)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    <QuerySet [<Book: 西游记:233.00>, <Book: 放风筝的人:14.11>, <Book: 北京折叠:11.11>, <Book: 水浒传:11.00>]>
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` ORDER BY `app01_book`.`price` DESC LIMIT 21; args=()
    View Code

    它的sql语句用的是desc

    count(): 返回数据库中匹配查询的对象数量。

    它的返回结果数据类型是int

    它是queryset的终止函数。为什么呢?因为它不能进行链式操作!

    下面这种,就属于链式操作。因为queryset可以调用API接口,只要前一个接口的返回值是queryset,它可以可以一直调用API接口,除非遇到返回值不是queryset的情况下,链式操作,才可以终止。因为count的返回值是int,所以到这里,就结束了!不能再调用API接口了!

    Book.objects.all().filter(price__gt=100).order_by("pirce").count()

    举例:

    修改query视图函数

    def query(request):
        obj = Book.objects.all().count()
        print(obj)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    4
    (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.000) SELECT COUNT(*) AS `__count` FROM `app01_book`; args=()
    View Code

    obj的返回结果为4

    exists(): 如果QuerySet包含数据,就返回True,否则返回False

    它的返回结果是一个布尔值

    举例:如果表里面有书,输入ok,否则输出none

    修改query视图函数,使用常规方法

    def query(request):
        ret = Book.objects.all()
        if ret:
            print('ok')
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    ok
    (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
    (0.001) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book`; args=()
    View Code

    ret结果为ok,它使用全表查询,但是这样有一个bug

    如果数据库有1000万本,这样一查,数据库就崩溃了。

    修改query视图函数,使用exists

    def query(request):
        ret = Book.objects.all().exists()
        if ret:
            print('ok')
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    ok
    (0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.001) SELECT (1) AS `a` FROM `app01_book` LIMIT 1; args=()
    View Code

    ret结果为ok,它用limit 1。它只查询了一条记录!

    即使数据库记录过多,也不影响。这样才是合理的!

    上述这些API方法,都是QuerySet在调用

    下面即将讲到的values,values_list,distinct。是一系列操作!

    values(*field): 返回一个ValueQuerySet

    它是一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列

    它的返回结果是一个特殊的QuerySet,列表每一个元素都是字典

    除了使用for循环之外,还有一个更好的方式。使用values,它内部封装了for循环

    举例:查询所有书籍名称

    修改query视图函数

    def query(request):
        ret = Book.objects.all().values("title")
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.000) SELECT `app01_book`.`title` FROM `app01_book` LIMIT 21; args=()
    

    <QuerySet [{'title': '北京折叠'}, {'title': '放风筝的人'}, {'title': '水浒传'}, {'title': '西游记'}]>

    View Code

    values返回的是QuerySet,列表的每一个元素都是字典。

    values可以接收多个参数,比如

    ret = Book.objects.all().values("title","price")

    字典的key,就是参数。一个字典,对应一条记录。

    跟上面讲的QuerySet区别就在于:

    不加values,QuerySet存放的是model对象。

    加了values之后,QuerySet存放的是字典。

    查询某一个字段时,推荐使用values

    values_list(*field):   values返回的是一个字典序列

    它与values()非常相似,它返回的是一个元组序列

    它的返回结果是一个特殊的QuerySet,列表每一个元素都是元组

    举例:

    修改query视图函数

    def query(request):
        book_list = Book.objects.all().values_list("title","price","pub_date")
        print(book_list)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.000) SELECT `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date` FROM `app01_book` LIMIT 21; args=()
    

    <QuerySet [('北京折叠', Decimal('11.11'), datetime.date(2012, 12, 12)), ('放风筝的人', Decimal('14.11'), datetime.date(2017, 12, 12)), ('西游记', Decimal('233.00'), datetime.date(2018, 7, 1)), ('水浒传', Decimal('11.00'), datetime.date(2018, 7, 2))]>

    View Code

    values_list和values的区别在于:values_list的类型是元组,vallues是字典。

    distinct(): 从返回结果中剔除重复纪录

    它的返回结果是QuerySet,注意:是一个常规的QuerySet

    修改表记录,将前2本书的价格修改为一样的。

    使用原生sql查询价格,去除重复的值

    mysql> select distinct(price) from app01_book;
    +--------+
    | price  |
    +--------+
    | 100.00 |
    | 233.00 |
    |  11.00 |
    +--------+
    3 rows in set (0.00 sec)
    View Code

    如果使用distinct对主键做去重,是没有意义的。因为主键是唯一的!

    mysql> select distinct(nid) from app01_book;
    +-----+
    | nid |
    +-----+
    |   1 |
    |   2 |
    |   5 |
    |   3 |
    +-----+
    4 rows in set (0.01 sec)
    View Code

    对所有字段做去重,也是没有意义的,因为每一条记录,不可能有重复的,这不还有主键嘛

    修改query视图函数

    def query(request):
        ret = Book.objects.all().distinct()
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    <QuerySet [<Book: 北京折叠:100.00>, <Book: 放风筝的人:100.00>, <Book: 西游记:233.00>, <Book: 水浒传:11.00>]>
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.000) SELECT DISTINCT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` LIMIT 21; args=()
    View Code

    所有记录都有了,毫无意义

    举例:查看所有书籍的价格,结果是不重复的

    修改query视图函数

    def query(request):
        ret = Book.objects.all().values("price").distinct()
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.000) SELECT DISTINCT `app01_book`.`price` FROM `app01_book` LIMIT 21; args=()
    

    <QuerySet [{'price': Decimal('100.00')}, {'price': Decimal('233.00')}, {'price': Decimal('11.00')}]>

    View Code

    举例:查看所有书籍的价格以及出版社,价格和出版社同时不能重复

    修改query视图函数

    def query(request):
        ret = Book.objects.all().values("price","publish").distinct()
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    <QuerySet [{'publish': '苹果出版社', 'price': Decimal('100.00')}, {'publish': '橘子出版社', 'price': Decimal('233.00')}, {'publish': '橘子出版社', 'price': Decimal('11.00')}]>
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.001) SELECT DISTINCT `app01_book`.`price`, `app01_book`.`publish` FROM `app01_book` LIMIT 21; args=()
    View Code

    发现结果只有3条,它使用了组合去重。2个字段,同时不唯一!

    基于双下划线的模糊查询

    Book.objects.filter(price__in=[100,200,300])
    Book.objects.filter(price__gt=100)
    Book.objects.filter(price__lt=100)
    Book.objects.filter(price__range=[100,200])
    Book.objects.filter(title__contains="python")
    Book.objects.filter(title__icontains="python")
    Book.objects.filter(title__startswith="py")
    Book.objects.filter(pub_date__year=2012)
    View Code

    字段名__gt(大于)

    举例:查询价格大于100的

    不能这么写

    ret = Book.objects.filter(price>100)
    View Code

    正确写法:

    def query(request):
        ret = Book.objects.filter(price__gt=100)
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    <QuerySet [<Book: 西游记:233.00>]>
    (0.001) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`price` > '100' LIMIT 21; args=(Decimal('100'),)
    View Code

    价格大于100的,只有西游记

    字段名__lt(小于)

    举例:查询价格小于100的

    修改query视图函数

    def query(request):
        ret = Book.objects.filter(price__lt=100)
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`price` < '100' LIMIT 21; args=(Decimal('100'),)
    

    <QuerySet [<Book: 水浒传:11.00>]>

    View Code

    价格小于100的,只有水浒传

    字段名__lte(小于等于)

    举例:查询价格小于等于100的

    修改query视图函数

    def query(request):
        ret = Book.objects.filter(price__lte=100)
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    <QuerySet [<Book: 北京折叠:100.00>, <Book: 放风筝的人:100.00>, <Book: 水浒传:11.00>]>
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.000) SELECT VERSION(); args=None
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`price` <= '100' LIMIT 21; args=(Decimal('100'),)
    View Code

    价格小于等于100的,有北京折叠,放风筝的人,水浒传

    字段名__gte(大于等于)

    举例:查询价格小于等于100的

    修改query视图函数

    def query(request):
        ret = Book.objects.filter(price__gte=100)
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    <QuerySet [<Book: 北京折叠:100.00>, <Book: 放风筝的人:100.00>, <Book: 西游记:233.00>]>
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.001) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`price` >= '100' LIMIT 21; args=(Decimal('100'),)
    View Code

    价格小于等于100的,有北京折叠,放风筝的人,西游记

    字段名__in(支持多个选择)

    举例:查询价格分别等于100,200,300的记录

    修改query视图函数

    def query(request):
        ret = Book.objects.filter(price__in=[100,200,300])
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`price` IN ('200', '100', '300') LIMIT 21; args=(Decimal('200'), Decimal('100'), Decimal('300'))
    [27/Jun/2018 20:58:08] "GET /query/ HTTP/1.1" 200 12
    <QuerySet [<Book: 北京折叠:100.00>, <Book: 放风筝的人:100.00>]>
    View Code

    价格等于100,200,300的有 北京折叠,放风筝的人

    字段名__range(介于两个值之间的数据范围)

    举例:查询价格在100到233之间的记录

    修改query视图函数

    def query(request):
        ret = Book.objects.filter(price__range=[100,300])
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    <QuerySet [<Book: 北京折叠:100.00>, <Book: 放风筝的人:100.00>, <Book: 西游记:233.00>]>
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`price` BETWEEN '100' AND '300' LIMIT 21; args=(Decimal('100'), Decimal('300'))
    View Code

    价格在100到233之间的有 北京折叠,放风筝的人,西游记

    字段名__startswith(以什么开头的)

    举例:查询以"北京"开头的书名有哪些

    修改query视图函数

    def query(request):
        ret = Book.objects.filter(title__startswith="北京")
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`title` LIKE BINARY '北京%' LIMIT 21; args=('北京%',)
    

    <QuerySet [<Book: 北京折叠:100.00>]>

    View Code

    以"北京"开头的书名的有  北京折叠

    字段名__contains(以什么结尾)

    举例:查询书名包含“传”的有哪些

    修改query视图函数

    def query(request):
        ret = Book.objects.filter(title__contains="")
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    <QuerySet [<Book: 水浒传:11.00>]>
    (0.001) SELECT @@SQL_AUTO_IS_NULL; args=None
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.001) SELECT VERSION(); args=None
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`title` LIKE BINARY '%传%' LIMIT 21; args=('%传%',)
    View Code

    书名包含“传”的有 水浒传

    字段名__year(查询某年)

    举例:查询出版日期是2018年的有哪些

    修改query视图函数

    def query(request):
        ret = Book.objects.filter(pub_date__year="2018")
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">查询成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.000) SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`, `app01_book`.`publish`, `app01_book`.`is_pub` FROM `app01_book` WHERE `app01_book`.`pub_date` BETWEEN '2018-01-01' AND '2018-12-31' LIMIT 21; args=('2018-01-01', '2018-12-31')
    

    <QuerySet [<Book: 西游记:233.00>, <Book: 水浒传:11.00>]>

    View Code

    出版日期是2018年的有 西游记,水浒传

    删除表纪录

    删除方法就是 delete()。它运行时立即删除对象而不返回任何值。例如:

    model_obj.delete()

    你也可以一次性删除多个对象。每个 QuerySet 都有一个 delete() 方法,它一次性删除 QuerySet 中所有的对象。

    它的返回值是元组,元组第一个值,是执行状态。1表示成功,0表示失败!

    例如,下面的代码将删除 pub_date 是2005年的 Entry 对象:

    Entry.objects.filter(pub_date__year=2005).delete()

    在 Django 删除对象时,会模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。例如:

    b = Blog.objects.get(pk=1)
    # This will delete the Blog and all of its Entry objects.
    b.delete()

    要注意的是: delete() 方法是 QuerySet 上的方法,但并不适用于 Manager 本身。这是一种保护机制,是为了避免意外地调用 Entry.objects.delete() 方法导致 所有的 记录被误删除。如果你确认要删除所有的对象,那么你必须显式地调用:

    Entry.objects.all().delete()  

    如果不想级联删除,可以设置为:

    pubHouse = models.ForeignKey(to='Publisher', on_delete=models.SET_NULL, blank=True, null=True)

    举例:删除价格等于100的

    修改urls.py,增加delbook路径

    urlpatterns = [
        path('admin/', admin.site.urls),
        path('add/', views.add),
        path('query/', views.query),
        path('change/', views.change),
        path('delbook/', views.delbook),
    ]
    View Code

    修改views.py,增加delbook视图函数

    注意:修改是基于查询的结果来修改的。所以是先有查询,再有修改!

    def delbook(request):
        ret = Book.objects.filter(price=100).delete()
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">删除成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    访问页面

    查看控制台输出信息:

    (0.001) DELETE FROM `app01_book` WHERE `app01_book`.`price` = '100'; args=(Decimal('100'),)
    (1, {'app01.Book': 1})
    View Code

     输出1,表示删除成功!

    查看表记录,点击刷新按钮,发现少了一条记录!

    QuerySet和model都可以调用delete

    举例:查询价格小于100的,并将第一条记录删除

    修改delbook视图函数

    def delbook(request):
        ret = Book.objects.filter(price__lte=100).delete()
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">删除成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    查看控制台输出信息:

    (0.000) DELETE FROM `app01_book` WHERE `app01_book`.`price` <= '100'; args=(Decimal('100'),)
    [27/Jun/2018 21:41:49] "GET /delbook/ HTTP/1.1" 200 12
    (1, {'app01.Book': 1})
    View Code

    输出结果为1,说明删除成功了!

    查看表记录,点击刷新按钮,发现少了一条记录!

    举例3:根据url的id值,来删除对应的记录

    如果url的id为2,就删除nid为2的记录

    修改urls.py,为delbook增加有名分组

    注意:要导入re_path模块,完整代码如下:

    from django.contrib import admin
    from django.urls import path,re_path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('add/', views.add),
        path('query/', views.query),
        path('change/', views.change),
        re_path('delbook/(?P<id>d+)', views.delbook),
    ]
    View Code

    修改delbook视图函数

    def delbook(request,id):
        ret = Book.objects.filter(nid=id).delete()
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">删除成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    访问url: http://127.0.0.1:8000/delbook/3

    查看控制台输出信息:

    (0.001) DELETE FROM `app01_book` WHERE `app01_book`.`nid` = 3; args=(3,)
    (1, {'app01.Book': 1})
    View Code

    输出结果为1,说明删除成功了!

    查看表记录,点击刷新按钮,发现少了一条记录!

    如果删除一条不存在的记录呢?

    访问url:http://127.0.0.1:8000/delbook/4

    查看控制台输出信息:

    (0, {'app01.Book': 0})
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.001) SELECT VERSION(); args=None
    (0.001) DELETE FROM `app01_book` WHERE `app01_book`.`nid` = 4; args=(4,)
    View Code

    输出结果为0,说明删除失败了!

    但是页面提示删除成功是不对的。

    修改delbook视图函数

    def delbook(request,id):
        ret = Book.objects.filter(nid=id).delete()
        print(ret)
        print(ret,type(ret))
    
    </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> ret[0]:
        </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">删除成功</span><span style="color: #800000;">"</span><span style="color: #000000;">)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">删除失败</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    再次访问url:http://127.0.0.1:8000/delbook/4

    查看控制台输出信息:

    (0, {'app01.Book': 0})
    (0.001) SELECT @@SQL_AUTO_IS_NULL; args=None
    (0, {'app01.Book': 0}) <class 'tuple'>
    (0.000) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
    (0.000) SELECT VERSION(); args=None
    (0.000) DELETE FROM `app01_book` WHERE `app01_book`.`nid` = 4; args=(4,)
    View Code

    它的返回值是一个元组,通过取第一个元素,就可以得到数字0。那么就可以进行if判断了!

    修改表纪录

    Book.objects.filter(title__startswith="py").update(price=120)

      此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。

    update的返回值为int。1表示成功,0表示失败。

    举例:修改nid为1的记录,将价格修改为1000元

    修改urls.py,增加change路径

    urlpatterns = [
        path('admin/', admin.site.urls),
        path('add/', views.add),
        path('query/', views.query),
        path('change/', views.change),
    ]
    View Code

    修改views.py,增加change视图函数

    注意:修改是基于查询的结果来修改的。所以是先有查询,再有修改!

    def change(request):
        nid = 1
        ret = Book.objects.filter(nid=nid).update(price=1000)
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">修改成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    访问页面

    查看控制台输出信息:

    (0.001) UPDATE `app01_book` SET `price` = '1000.00' WHERE `app01_book`.`nid` = 1; args=('1000.00', 1)
    1
    View Code

    ret的返回结果为1,表示修改成功!

    查看表记录,点击刷新按钮,发现价格已经修改了!

    举例:修改西游记的价格为133以及is_pub修改为1

    修改change视图函数

    def change(request):
        nid = 3
        ret = Book.objects.filter(nid=nid).update(price=133,is_pub=1)
        print(ret)
    
    </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">修改成功</span><span style="color: #800000;">"</span>)</pre>
    
    View Code

    刷新页面,查看控制台输出信息:

    (0.001) UPDATE `app01_book` SET `price` = '133.00', `is_pub` = 1 WHERE `app01_book`.`nid` = 3; args=('133.00', True, 3)
    1
    View Code

    ret的返回结果为1,表示修改成功!

    查看表记录,点击刷新按钮,发现价格和is_pub已经修改了!

    章节作业

    1. 查询操作练习

    1. 查询苹果出版社出版过的价格大于200的书籍
    2. 查询2017年6月出版的所有以py开头的书籍名称
    3. 查询价格为50,100或者150的所有书籍名称及其出版社名称 
    4. 查询价格在100到200之间的所有书籍名称及其价格
    5. 查询所有人民出版社出版的书籍的价格(从高到低排序,去重)
    6. 查询价格大于200的书籍的个数
    7. 查询价格不等于100的所有书籍
    8. 查询苹果出版社出版的书籍中的第3-7本(前提存在足够数量的书籍)
    View Code

    2. 图书管理系统

    实现功能:book单表的增删改查

    第一题答案:

    准备基础数据:

    #截断表记录
    mysql> TRUNCATE TABLE app01_book;
    Query OK, 0 rows affected (0.19 sec)
    

    #插入数据:
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES ('1', 'python基础', '2017-06-01', '200.00', '人民出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '2', '西游记', '2017-08-08', '100.00', '苹果出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '3', '红楼梦', '2017-08-10', '50.00', '苹果出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '4', '水浒传', '2017-08-25', '150.00', '人民出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '5', '三国演义', '2017-12-20', '88.00', '苹果出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '6', 'python爬虫', '2018-02-10', '300.00', '人民出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '7', 'python大数据', '2018-05-15', '350.00', '苹果出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '8', 'java', '2017-08-11', '55.00', '苹果出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '9', 'go', '2018-06-04', '66.00', '苹果出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '10', 'php', '2018-06-08', '99.00', '苹果出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '11', 'c', '2018-05-22', '156.00', '苹果出版社', '1');
    INSERT INTO app01_book (nid, title, pub_date, price, publish, is_pub) VALUES (
    '12', 'c++', '2018-04-17', '650.00', '苹果出版社', '1');

    View Code

    1. 查询苹果出版社出版过的价格大于200的书籍

    ret = Book.objects.filter(price__gt=200, publish='苹果出版社', is_pub=True).values('title', 'price')
    for i in ret:
        print(i['title'], i['price'])
    View Code

    查询结果:

    python大数据 350.00
    c++ 650.00
    View Code

    2. 查询2017年6月出版的所有以py开头的书籍名称

    ret = Book.objects.filter(title__startswith='py',pub_date__year=2017, pub_date__month=6).values('title')
    for i in ret:
        print(i['title'])
    View Code

    查询结果:

    python基础

    3. 查询价格为50,100或者150的所有书籍名称及其出版社名称 

    ret = Book.objects.filter(price__in=[50,100,150]).values('title', 'publish')
    for i in ret:
        print(i['title'], i['publish'])
    View Code

    查询结果:

    西游记 苹果出版社
    红楼梦 苹果出版社
    水浒传 人民出版社
    View Code

    4. 查询价格在100到200之间的所有书籍名称及其价格

    ret = Book.objects.filter(price__range=[100, 200]).values('title', 'price')
    for i in ret:
        print(i['title'], i['price'])
    View Code

    查询结果:

    python基础 200.00
    西游记 100.00
    水浒传 150.00
    c 156.00
    View Code

    5. 查询所有人民出版社出版的书籍的价格(从高到低排序,去重)

    ret = Book.objects.filter(publish='人民出版社').order_by('price').reverse().values('title','price','publish')
    ..distinct()
    for i in ret:
        print(i['title'], i['price'],i['publish'])
    View Code

    查询结果:

    python爬虫 300.00 人民出版社
    python基础 200.00 人民出版社
    水浒传 150.00 人民出版社
    View Code

    6. 查询价格大于200的书籍的个数

    ret = Book.objects.filter(price__gt=200).count()
    print(ret)
    View Code

    查询结果:3

    7. 查询价格不等于100的所有书籍

    ret = Book.objects.exclude(price=100).values('id', 'title', 'price', 'publish')
    for i in ret:
        print(i['id'], i['title'], i['price'], i['publish'])
    View Code

    查询结果:

    1 python基础 200.00 人民出版社
    

    3 红楼梦 50.00 苹果出版社

    4 水浒传 150.00 人民出版社

    5 三国演义 88.00 苹果出版社

    6 python爬虫 300.00 人民出版社

    7 python大数据 350.00 苹果出版社

    8 java 55.00 苹果出版社

    9 go 66.00 苹果出版社

    10 php 99.00 苹果出版社

    11 c 156.00 苹果出版社

    12 c++ 650.00 苹果出版社

    View Code

    8. 查询苹果出版社出版的书籍中的第3-7本(前提存在足够数量的书籍)

    ret = Book.objects.filter(publish='苹果出版社')[3:7].values('id','title','price','publish')
    for i in ret:
        print(i['id'], i['title'], i['price'], i['publish'])
    View Code

    查询结果:

    7 python大数据 350.00 苹果出版社
    

    8 java 55.00 苹果出版社

    9 go 66.00 苹果出版社

    10 php 99.00 苹果出版社

    View Code

    参考资料:

    Django 基础教程

    转载声明:
    作者:肖祥
    出处: https://www.cnblogs.com/xiao987334176/

  • 相关阅读:
    kubectl 命令详解
    codeforce344 C report
    poj3041 建图+最小顶点覆盖(最大匹配数)
    poj1637 混合欧拉回路的判定
    poj1149 最大流好题 难在建图 好题
    targan 算法模板
    poj2186 强连通分量 targan算法的应用
    poj2723 2分 + 2-sat
    poj3061 尺取法
    poj3207 2-sat基础题
  • 原文地址:https://www.cnblogs.com/bqwzx/p/10160024.html
Copyright © 2011-2022 走看看