Django web 框架学习之旅(3)

《Django Web 框架》

目录

静态文件

  1. 什么是静态文件
    • 不能与服务器端做动态交互的文件都是静态文件
    • 如:图片,css,js,音频,视频,html文件(部分)
  2. 静态文件配置
    • 在 settings.py 中配置一下两项内容:
    1. 配置静态文件的访问路径
      • 通过哪个url地址找静态文件
      • STATIC_URL = ‘/static/’
      • 说明:
        • 指定访问静态文件时是需要通过 /static/xxx或 127.0.0.1:8000/static/xxx
        • xxx 表示具体的静态资源位置
    2. 配置静态文件的存储路径
      • 静态文件在服务器端的保存位置
      • STATICFILES_DIRS=(os.path.join(BASE_DIR,‘static’),)
    3. 示例:
      # file: setting.py
      STATICFILES_DIRS = [
          os.path.join(BASE_DIR, "static")
      ]
      
  3. 访问静态文件
    1. 使用静态文件的访问路径进行访问

      • 访问路径: STATIC_URL=/static/
      • 示例:
        <img src="/static/images/lena.jpg">
        <img src="http://127.0.0.1:8000/static/images/lena.jpg">
        
    2. 通过 {% static %}标签访问静态文件
      {% static %}表示的就是静态文件访问路径

      1. 加载 static
        {% load static %}
      2. 使用静态资源时
        语法:{% static ‘静态资源路径’ %}
        <img src="{% static ‘images/lena.jpg’ %}">
    • 示例:
      # file: url.py
      from . import views
      
      urlpatterns = [
          url(r'^admin/', admin.site.urls),
          url(r'^show_image', views.show_image)
      ]
      # file: views.py
      from django.shortcuts import render
      
      def show_image(request):
          return render(request, "show_image.html")
      
      <html>
      <head></head>
      <body>
      <h1>this is lena!</h1>
      <img src="/static/images/lena.jpg">
      <h1>this is templates lena!</h1>
      {% load static %}
      <img src="{% static 'images/lena.jpg' %}">
      </body>
      </html>
      

Django中的应用 - app

什么是应用(app)

  • 应用在Django项目中是一个独立的业务模块,可以包含自己的路由,视图,… …
  • Django中,主文件夹是不处理用户具体请求的.主文件夹的作用是做项目的初始化以及请求的分发(分布式请求处理).具体的请求是由应用来进行处理的

创建应用app

  • 创建应用的指令
    • python3 manage.py startapp 应用名称
    • 如:
      • python3 manage.py startapp music

Django应用的结构组成

1. `migrations` 文件夹
    - 保存数据迁移的中间文件
2. `__init__.py`
    - 应用子包的初始化文件
3. `admin.py`
    - 应用的后台管理配置文件
4. `apps.py`
    - 应用的属性配置文件
5. `models.py`
    - 与数据库相关的模型映射类文件
6. `tests.py`
    - 应用的单元测试文件
7. `views.py`
    - 定义视图处理函数的文件
  • 配置安装应用
    • 在 settings.py 中配置应用, 让此应用能和整个项目融为一体
      # file : settings.py 
      INSTALLED_APPS = [
          ... ...,
          '自定义应用名称'
      ]
      
      
    • 如:
      INSTALLED_APPS = [
          # ....
          'user',  # 用户信息模块
          'music',  # 收藏模块
      ]
      
  • 应用的分布式路由
    • 使用include 函数让某个正则匹配后关联分支到某个app
    # file : <项目名>/urls.py
    from django.conf.urls import include
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^music/', include('music.urls')),
        url(r'^sport/',include('sport.urls')),
        url(r'^news/',include('news.urls')),
    ]
    # file : <App名>/urls.py
    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        # 购物车模块用到的路由
        url(r'^page1', views.page1),
        url(r'^page2', views.page2),
        url(r'^page3', views.page3),
        # ...
    ]
    
    
    
    

数据库 和 模型

Django下使用mysql数据库

  1. 安装 pymysql包

    • 用作 python 和 mysql 的接口
      • $ sudo pip3 install pymysql
    • 安装 mysql 客户端(非必须)
      $ sudo pip3 install mysqlclient
  2. 创建 和 配置数据库

    1. 创建数据库
      • 创建 create database 数据库名 default charset utf8 collate utf8_general_ci;
      create database mywebdb default charset utf8 ;
      
    2. 数据库的配置
      • sqlite 数据库配置
      # file: settings.py
      DATABASES = {
          'default': {
                  'ENGINE': 'django.db.backends.sqlite3',
                  'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
          }
      }
      
      • mysql 数据库配置
      DATABASES = {
              
              
          'default' : {
              
              
              'ENGINE': 'django.db.backends.mysql',
              'NAME': 'mywebdb',  # 数据库名称,需要自己定义
              'USER': 'root',
              'PASSWORD': '123456',  # 管理员密码
              'HOST': '127.0.0.1',
              'PORT': 3306,
          }
      }
      
    3. 关于数据为的SETTING设置
      1. ENGINE

        • 指定数据库的后端引擎
        'django.db.backends.mysql'
        'django.db.backends.sqlite3'
        'django.db.backends.oracle'
        'django.db.backends.postgresql'
        
        • mysql引擎如下:
          • ‘django.db.backends.mysql’
      2. NAME

        • 指定要连接的数据库的名称
        • 'NAME': 'mywebdb'
      3. USER

        • 指定登录到数据库的用户名
        • 'USER':'root'
      4. PASSWORD

        • 接数据库时使用的密码。
        • 'PASSWORD':'123456'
      5. HOST

        • 连接数据库时使用哪个主机。
        • 'HOST':'127.0.0.1'
      6. PORT

        • 连接数据库时使用的端口。
        • 'PORT':'3306'
    4. 添加 mysql 支持
      • 安装pymysql 模块
        • $ sudo pip install pymysql
      • 修改项目中__init__.py 加入如下内容来提供pymysql引擎的支持
        import pymysql
        pymysql.install_as_MySQLdb()
        
  3. 数据库的迁移

    • 迁移是Django同步您对模型所做更改(添加字段,删除模型等) 到您的数据库模式的方式
    1. 生成或更新迁移文件
      • 将每个应用下的models.py文件生成一个中间文件,并保存在migrations文件夹中
      • python3 manage.py makemigrations
    2. 执行迁移脚本程序
      • 执行迁移程序实现迁移。将每个应用下的migrations目录中的中间文件同步回数据库
      • python3 manage.py migrate
    3. 查看迁移执行的SQL语句
      • 将 sqlmigrate, 显示迁移的sql语句
      • python3 manage.py sqlmigrate

数据库迁移的错误处理方法

  • 当执行 $ python3 manage.py makemigrations 出现如下迁移错误时的处理方法

    • 错误信息
      $ python3 manage.py makemigrations
      You are trying to change the nullable field 'title' on book to non-nullable without a default; we can't do that (the database needs something to populate existing rows).
      Please select a fix:
      1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
      2) Ignore for now, and let me handle existing rows with NULL myself (e.g. because you added a RunPython or RunSQL operation to handle NULL values in a previous data migration)
      3) Quit, and let me add a default in models.py
      Select an option: 
      
    • 翻译为中文如下:
      $ python3 manage.py makemigrations
      您试图将图书上的可空字段“title”更改为非空字段(没有默认值);我们不能这样做(数据库需要填充现有行)。
      请选择修复:
      1)现在提供一次性默认值(将对所有现有行设置此列的空值)
      2)暂时忽略,让我自己处理空值的现有行(例如,因为您在以前的数据迁移中添加了RunPython或RunSQL操作来处理空值)
      3)退出,让我在models.py中添加一个默认值
      选择一个选项:
      
    • 错误原因
      • 当将如下代码
      class Book(models.Model):
          title = models.CharField("书名", max_length=50, null=True)
      
      • 去掉 null=True 改为如下内容时会出现上述错误
      class Book(models.Model):
          title = models.CharField("书名", max_length=50)
      
      • 原理是 此数据库的title 字段由原来的可以为NULL改为非NULL状态,意味着原来这个字段可以不填值,现在改为必须填定一个值,那填什么值呢?此时必须添加一个缺省值。
    • 处理方法:
      1. 选择1 手动给出一个缺省值,在生成 bookstore/migrations/000x_auto_xxxxxxxx_xxxx.py 文件时自动将输入的值添加到default参数中
      2. 暂时忽略,以后用其它的命令处理缺省值问题(不推荐)
      3. 退出当前生成迁移文件的过程,自己去修改models.py, 新增加一个default=XXX 的缺省值(推荐使用)
  • 数据库的迁移文件混乱的解决办法

    1. 删除 所有 migrations 里所有的 000?_XXXX.py (__init__.py除外)
    2. 删除 数据表
      • sql> drop database mywebdb;
    3. 重新创建 数据表
      • sql> create datebase mywebdb default charset…;
    4. 重新生成migrations里所有的 000?_XXXX.py
      • python3 manage.py makemigrations
    5. 重新更新数据库
      • python3 manage.py migrate

模型(Models)

  • 模型是提供数据信息的数据库接口。

  • 模型是数据的唯一的、确定的信息源。 它包含你所储存数据的必要字段和行为。

  • 通常,每个模型对应数据库中唯一的一张表。每个模型的实例对应数据表中的一条记录

  • 模型说明:

    • 每个模型都是一个Python类,每个模型都是django.db.models.Model的子类。
    • 每一个模型属性都代表数据库中的一个表。
    • 通过所有这一切,Django为你提供一个自动生成的数据库访问API;

Python 数据库模型 - Models

  1. ORM框架
    • ORM(Object Relationship Mapping)即对象关系映射,它允许你使用类和对象对数据库进行交互(使用类和对象和使用 SQL一样且更方便各种操作)。
    • ORM
      Object Relationship Mapping
        对象    关系         映射
      
    • 三大特征:
      1. 表 到 类的映射
      2. 数据类型的映射
      3. 关系映射
  2. 模型示例:
    • 此示例为添加一个bookstore_book 数据表来存放图书馆中书目信息
    • 添加一个 bookstore 的 app
    $ python3 manage.py startapp bookstore
    
    • 添加模型类并注册app
    # file : bookstore/models.py
    from django.db import models
    
    class Book(models.Model):
        title = models.CharField("书名", max_length=50)
        price = models.DecimalField('定价', max_digits=7, decimal_places=2)
    # file : setting.py
    INSTALLED_APPS = [
        ...
        'bookstore',
    ]
    
    • 生成迁移脚本文件bookstore/migrations/0001_initial.py并进行迁移
    $ python3 manage.py makemigrations
    Migrations for 'bookstore':
    bookstore/migrations/0001_initial.py
        - Create model Book
    $ python3 manage.py migrate
    Operations to perform:
    Apply all migrations: admin, auth, bookstore, contenttypes, sessions
    Running migrations:
    Applying bookstore.0001_initial... OK
    
    • 查看数据表
    $ mysql -u root -p
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mygoods            |
    | mysql              |
    | mywebdb            |
    | onlybuyp           |
    | performance_schema |
    | sys                |
    | test_db            |
    +--------------------+
    8 rows in set (0.00 sec)
    
    mysql> use mywebdb
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Database changed
    mysql> show tables;
    +----------------------------+
    | Tables_in_mywebdb          |
    +----------------------------+
    | auth_group                 |
    | auth_group_permissions     |
    | auth_permission            |
    | auth_user                  |
    | auth_user_groups           |
    | auth_user_user_permissions |
    | bookstore_book             |  <<== 新加表
    | django_admin_log           |
    | django_content_type        |
    | django_migrations          |
    | django_session             |
    +----------------------------+
    11 rows in set (0.00 sec)
    
    mysql> desc bookstore_book;
    +-------+--------------+------+-----+---------+----------------+
    | Field | Type         | Null | Key | Default | Extra          |
    +-------+--------------+------+-----+---------+----------------+
    | id    | int(11)      | NO   | PRI | NULL    | auto_increment |
    | title | varchar(50)  | NO   |     | NULL    |                |
    | price | decimal(7,2) | NO   |     | NULL    |                |
    +-------+--------------+------+-----+---------+----------------+
    3 rows in set (0.00 sec)
    
    • 表bookstore_book 即为模型 Book 类对应的数据表
      • id 为主键,当设定主键时会自动添加id字段为主键
      • 如果更新模型类 models.py 中的内容时需要运行 makemigrations 和 migrate 子命名来更新和同步数据库
      • 在开发阶段如果同步数据库出错。用sql> drop database 数据库名 删除数据库后重新迁移数据库
      • 在 xxx_app/migrations/*.py 下的文件是自动生成的迁移脚本文件,可以手动删除且在下一次迁移时自动生成
  1. 编写模型类Models

    • 模型类需继承自django.db.models.Model
      1. Models的语法规范
        from django.db import models
        class CLASSNAME类名(models.Model):
            NAME=models.FIELD_TYPE(FIELD_OPTIONS)
        
      2. CLASSNAME
        • 实体类名,表名组成一部分,建议类名首字母大写
        • 默认表名组成规范:
          • 应用名称_classname
      3. NAME
        • 属性名,映射回数据库就是字段名
      4. FIELD_TYPE
        • 字段类型:映射到表中的字段的类型
  2. FIELD_TYPE 类型及含义

    1. BooleanField()

      • 数据库类型:tinyint(1)
      • 编程语言中:使用True或False来表示值
      • 在数据库中:使用1或0来表示具体的值
    2. CharField()

      • 数据库类型:varchar
      • 注意:
        • 必须要指定max_length参数值
    3. DateField()

      • 数据库类型:date
      • 作用:表示日期
      • 编程语言中:使用字符串来表示具体值
      • 参数:
        • DateField.auto_now: 每次保存对象时,自动设置该字段为当前时间(取值:True/False)。
        • DateField.auto_now_add: 当对象第一次被创建时自动设置当前时间(取值:True/False)。
        • DateField.default: 设置当前时间(取值:字符串格式时间如: ‘2019-6-1’)。
        • 以上三个参数只能多选一
    4. DateTimeField()

      • 数据库类型:datetime(6)
      • 作用:表示日期和时间
      • auto_now_add=True
    5. DecimalField()

      • 数据库类型:decimal(x,y)

      • 编程语言中:使用小数表示该列的值

      • 在数据库中:使用小数

      • 参数:

        • DecimalField.max_digits: 位数总数,包括小数点后的位数。 该值必须大于等于decimal_places.
        • DecimalField.decimal_places: 小数点后的数字数量
      • 示例:

        money=models.DecimalField(
            max_digits=7,
            decimal_places=2
        )
        
    6. FloatField()

      • 数据库类型:double
      • 编程语言中和数据库中都使用小数表示值
    7. EmailField()

      • 数据库类型:varchar
      • 编程语言和数据库中使用字符串
    8. IntegerField()

      • 数据库类型:int
      • 编程语言和数据库中使用整数
    9. URLField()

      • 数据库类型:varchar(200)
      • 编程语言和数据库中使用字符串
    10. ImageField()

      • 数据库类型:varchar(100)
      • 作用:在数据库中为了保存图片的路径
      • 编程语言和数据库中使用字符串
      • 示例:
        image=models.ImageField(
            upload_to="static/images"
        )
        
      • upload_to:指定图片的上传路径
        在后台上传时会自动的将文件保存在指定的目录下
    11. TextField()

      • 数据库类型:longtext
      • 作用:表示不定长的字符数据

字段选项

  1. FIELD_OPTIONS
    • 字段选项,指定创建的列的额外的信息
    • 允许出现多个字段选项,多个选项之间使用,隔开
    1. primary_key
      • 如果设置为True,表示该列为主键
    2. null
      • 如果设置为True,表示该列值允许为空
      • 默认为False
    3. default
      • 设置所在列的默认值
    4. db_index
      • 如果设置为True,表示为该列增加索引
    5. unique
      • 如果设置为True,表示该列的值唯一
    6. db_column
      • 指定列的名称,如果不指定的话则采用属性名作为列名
    ex:
        创建一个属性,表示用户名称,长度30个字符,必须是唯一的,不能为空,添加索引

        name=models.CharField(max_length=30,unique=True,null=False,db_index=True)
# file : bookstore/models.py
from django.db import models

class Book(models.Model):
    title = models.CharField("书名", max_length=50)
    price = models.DecimalField('定价', max_digits=7, decimal_places=2)
    pub_house = models.CharField("出版社", max_length=50, default='清华大学出版社')
    pub_date = models.DateField('出版时间', default='1970-1-1')
    market_price = models.DecimalField('市价', max_digits=7, decimal_places=2, default=9999)
# file : bookstore/views.py
from django.http import HttpResponse
from . import models

def init_books(request):
    models.Book.objects.create(title='C', price=30, market_price=35, pub_house="清华大学出版社")
    models.Book.objects.create(title='C++', price=40, market_price=45, pub_house="清华大学出版社")
    models.Book.objects.create(title='Java', price=50, market_price=55, pub_house="清华大学出版社")
    models.Book.objects.create(title='Python', price=20, market_price=25, pub_house="清华大学出版社")
    models.Book.objects.create(title='Python3', price=60, market_price=65, pub_house="清华大学出版社")
    models.Book.objects.create(title='Django', price=70, market_price=75, pub_house="清华大学出版社")
    models.Book.objects.create(title='JQuery', price=90, market_price=85, pub_house="机械工业出版社")
    models.Book.objects.create(title='Linux', price=80, market_price=65, pub_house="机械工业出版社")
    models.Book.objects.create(title='Windows', price=50, market_price=35, pub_house="机械工业出版社")

    abook = models.Book(title="HTML5", price=90, market_price=105, pub_date='2019-1-1')  # 创建新书
    abook.save()  # 保存

    return HttpResponse("初始化成功")

  • 第一次执行视图views.py 中的init_books()函数时结果
mysql> select * from bookstore_book;
+----+---------+-------+--------------+------------+----------------+
| id | title   | price | market_price | pub_date   | pub_house      |
+----+---------+-------+--------------+------------+----------------+
|  1 | C       | 30.00 |        35.00 | 1970-01-01 | 清华大学出版社 |
|  2 | C++     | 40.00 |        45.00 | 1970-01-01 | 清华大学出版社 |
|  3 | Java    | 50.00 |        55.00 | 1970-01-01 | 清华大学出版社 |
|  4 | Python  | 20.00 |        25.00 | 1970-01-01 | 清华大学出版社 |
|  5 | Python3 | 60.00 |        65.00 | 1970-01-01 | 清华大学出版社 |
|  6 | Django  | 70.00 |        75.00 | 1970-01-01 | 清华大学出版社 |
|  7 | JQuery  | 90.00 |        85.00 | 1970-01-01 | 机械工业出版社 |
|  8 | Linux   | 80.00 |        65.00 | 1970-01-01 | 机械工业出版社 |
|  9 | Windows | 50.00 |        35.00 | 1970-01-01 | 机械工业出版社 |
| 10 | HTML5   | 90.00 |       105.00 | 2019-01-01 | 清华大学出版社 |
+----+---------+-------+--------------+------------+----------------+
10 rows in set (0.00 sec)

数据库的操作(CRUD操作)

  • CRUD是指在做计算处理时的增加(Create)、读取查询(Read)、更新(Update)和删除(Delete)
  • 数据换的增册改查可以通过模型的管理器实现
    • MyModel.objects 是管理器对象
创建数据对象
  • Django 使用一种直观的方式把数据库表中的数据表示成Python 对象
  • 创建数据中每一条记录就是创建一个数据对象
    1. Entry.objects.create(属性=值, 属性=值)
      • 返回值: 返回创建好的实体对象
    2. 创建Entry对象,并调用 save() 进行保存
      obj = Entry(属性=值,属性=值)
      obj.属性=值
      obj.save()
      无返回值,保存成功后,obj会被重新赋值
      
    3. 使用字典创建对象,并调用save()进行保存
      dic = {
          '属性1':'值',
          '属性2':'值2',
      }
      
      obj = Entry(**dic)
      obj.save()
      
    4. 示例1:
      try:
          abook = Book.objects.create(title='Python', pub='清华大学出版社')
          print(abook)
      except:
          print('创建对象失败')
      
    5. 示例2:
      try:
          abook = Book(title='Python', pub='清华大学出版社')
          abook.save
          print(abook)
      except:
          print('创建对象失败')
      
    6. 示例3:
      try:
          abook = Book()
          abook.title='Python'
          abook.pub='清华大学出版社'
          abook.save
          print(abook)
      except:
          print('创建对象失败')
      
查询数据
  • 数据库的查询需要使用管理器对象进行
  • 通过 Entry.objects 管理器方法调用查询接口
    方法 说明
    all() 查询全部记录,返回QuerySet查询对象
    get() 查询符合条件的单一记录
    filter() 查询符合条件的多条记录
    exclude() 查询符合条件之外的全部记录
  1. all()方法

    • 方法: all()
    • 用法: Entry.objects.all()
    • 作用: 查询Entry实体中所有的数据
      • 等同于
        • select * from tabel
    • 返回值: QuerySet容器对象,内部存放Entry 实例
    • 示例:
      from bookstore import models
      books = models.Book.object.all()
      for book in books:
          print("书名", book.title, '出版社:', book.pub)
      
  2. 在模型类中定义 def __str__(self): 方法可以将自定义默认的字符串

    class Book(models.Model):
        title = ...
        def __str__(self):
            return "书名: %s, 出版社: %s, 定价: %s" % (self.title, self.pub, self.price)
    
  3. 查询返回指定列(字典表示)

    • 方法: values(‘列1’, ‘列2’)
    • 用法: Entry.objects.values(…)
    • 作用: 查询部分列的数据并返回
      • select 列1,列2 from xxx
    • 返回值: QuerySet
      • 返回查询结果容器,容器内存字典,每个字典代表一条数据,
      • 格式为: {‘列1’: 值1, ‘列2’: 值2}
    • 示例:
      from bookstore import models
      books = models.Book.objects.values("title", "pub")
      for book in books:
          print("书名", book["title"], '出版社:', book['pub'])
          print("book=", book)
      
  4. 查询返回指定列(元组表示)

    • 方法:values_list(‘列1’,‘列2’)
    • 用法:Entry.objects.values_list(…)
    • 作用:
      • 返回元组形式的查询结果
    • 返回值: QuerySet容器对象,内部存放 元组
      • 会将查询出来的数据封装到元组中,再封装到查询集合QuerySet中
    • 示例:
      from bookstore import models
      books = models.Book.objects.values_list("title", "pub")
      for book in books:
          print("book=", book)  # ('Python', '清华大学出版社')...
      
  5. 排序查询

    • 方法:order_by

    • 用法:Entry.objects.order_by(’-列’,‘列’)

    • 作用:

      • 与all()方法不同,它会用SQL 语句的ORDER BY 子句对查询结果进行根据某个字段选择性的进行排序
    • 说明:

      • 默认是按照升序排序,降序排序则需要在列前增加’-'表示
    • 示例:

      from bookstore import models
      books = models.Book.objects.order_by("price")
      for book in books:
          print("书名:", book.title, '价格:', book.price)
      
  6. 根据条件查询多条记录

    • 方法: filter(条件)
    • 语法:
      Entry.objects.filter(属性1=值1, 属性2=值2)
      
    • 返回值:
      • QuerySet容器对象,内部存放 Entry 实例
    • 说明:
      • 当多个属性在一起时为与关系,即当Books.objects.filter(price=20, pub="清华大学出版社") 返回价格为20 出版社为"清华大学出版社"的全部图书
    • 示例:
      # 查询书中出版社为"清华大学出版社"的图书
      from bookstore import models
      books = models.Book.objects.filter(pub="清华大学出版社")
      for book in books:
          print("书名:", book.title)
      
      2. 查询Author实体中id为1并且isActive为True的
          - authors=Author.objects.filter(id=1,isActive=True)
      

字段查找

  • 字段查询是指如何指定SQL语句中 WHERE 子句的内容。
  • 字段查询需要通过QuerySet的filter(), exclude() and get()的关键字参数指定。
  • 非等值条件的构建,需要使用字段查询
  • 示例:
    # 查询作者中年龄大于30
    Author.objects.filter(age__gt = 30)
    # 对应
    SELECT .... WHERE AGE > 35;
    
查询谓词
  • 每一个查询谓词是一个独立的查询功能
  1. __exact : 等值匹配
    Author.objects.filter(id__exact=1)
    select * from author where id = 1
    
  2. __contains : 包含指定值
    Author.objects.filter(name__contains='w')
    select * from author where name like '%w%'
    
  3. __startswith : 以 XXX 开始
  4. __endswith : 以 XXX 开始
  5. __gt : 大于指定值
    Author.objects.filer(age__gt=50)
    select * from author where age > 50
    
  6. __gte : 大于等于
  7. __lt : 小于
  8. __lte : 小于等于
  9. __in : 查找数据是否在指定范围内
    • 示例
    Author.objects.filter(country__in=['中国','日本','韩国'])
    # 等同于
    select * from author where country in ('中国','日本','韩国')
    
  10. __range: 查找数据是否在指定的区间范围内
    # 查找年龄在某一区间内的所有作者
    Author.objects.filter(age__range=(35,50))
    # 等同于
    SELECT ... WHERE Author BETWEEN 35 and 50;
    
  11. 详细内容参见: https://yiyibooks.cn/xx/Django_1.11.6/ref/models/querysets.html
  • 示例

    Entry.objects.filter(id__gt=4)
    SQL等效:
    
    SELECT ... WHERE id > 4;
    
  • 练习:

    1. 查询Author表中age大于等于85的信息
      • Author.objects.filter(age__gte=85)
    2. 查询Author表中姓王的人的信息
      • Author.objects.filter(name__startswith='王')
    3. 查询Author表中Email中包含"wc"的人的信息
      • Author.objects.filter(email__contains='in')
  1. 不等的条件筛选

    • 语法:
      Entry.objects.exclude(条件)
    • 作用:
      • 返回不包含此 条件 的 作部的数据集
    • 示例:
      • 查询 清华大学出版社,价格大于50 以外的全部图书
      books = models.Book.objects.exclude(pub=清华大学出版社, price__lt=50)
      for book in books:
          print(book)
      
  2. 查询指定的一条数据

    • 语法:
      Entry.objects.get(条件)
    • 作用:
      • 返回满足条件的唯一一条数据
    • 返回值:
      • Entry 对象
    • 说明:
      • 该方法只能返回一条数据
      • 查询结果多余一条数据则抛出,Model.MultipleObjectsReturned异常
      • 查询结果如果没有数据则抛出Model.DoesNotExist异常
    • 示例:
      from bookstore import models
      book = models.Book.object.get(id=1)
      print(book.title)
      

修改数据记录

  1. 修改单个实体的某些字段值

      • 通过 get() 得到要修改的实体对象
      • 通过 对象.属性 的方式修改数据
    1. 保存

      • 通过 对象.save() 保存数据
    2. 如下:

      from bookstore import models
      abook = models.Book.objects.get(id=10)
      abook.market_price = "10.5"
      abook.save()
      
  2. 通过 QuerySet 批量修改 对应的全部字段

    • 直接调用QuerySet的update(属性=值) 实现批量修改
    • 如:
      # 将 id大于3的所有图书价格定为0元
      books = Book.objects.filter(id__gt=3)
      books.update(price=0)
      # 将所有书的零售价定为100元
      books = Book.objects.all()
      books.update(market_price=100)
      

删除记录

  • 删除记录是指删除数据库中的一条或多条记录
  • 删除单个Entry对象或删除一个查询结果集(QuerySet)中的全部对象都是调用 delete()方法
  1. 删除单个对象
    • 步骤
      1. 查找查询结果对应的一个数据对象
      2. 调用这个数据对象的delete()方法实现删除
    • 示例:
      try:
          auth = Author.objects.get(id=1)
          auth.delete()
      except:
          print(删除失败)
      
  2. 删除查询结果集
    • 步骤
      1. 查找查询结果集中满足条件的全部QuerySet查询集合对象
      2. 调用查询集合对象的delete()方法实现删除
    • 示例:
      # 删除全部作者中,年龄大于65的全部信息
      auths = Author.objects.filter(age__gt=65)
      auths.delete()
      

聚合查询

  • 聚合查询是指对一个数据表中的一个字段的数据进行部分或全部进行统计查询,查bookstore_book数据表中的全部书的平均价格,查询所有书的总个数等,都要使用聚合查询
  1. 不带分组聚合
    • 不带分组的聚合查询是指导将全部数据进行集中统计查询
    • 聚合函数:
      • 定义模块: django.db.models
      • 用法: from django.db.models import *
      • 聚合函数:
        • Sum, Avg, Count, Max, Min
    • 语法:
      • Entry.objects.aggregate(结果变量名=聚合函数(‘列’))
    • 返回结果:
      • 由 结果变量名和值组成的字典
      • 格式为:
        • `{“结果变量名”: 值}
    • 示例:
      # 得到所有书的平均价格
      from bookstore import models
      from django.db.models import Count
      result = models.Book.objects.aggregate(myAvg=Avg('price'))
      print("平均价格是:", result['myAvg'])
      print("result=", result)  # {"myAvg": 58.2}
      
      # 得到数据表里有多少本书
      from django.db.models import Count
      result = models.Book.objects.aggregate(mycnt=Count('title'))
      print("数据记录总个数是:", result['mycnt'])
      print("result=", result)  # {"mycnt": 10}
      
      
  2. 分组聚合
    • 分组聚合是指通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。

    • 语法:

      • QuerySet.annotate(结果变量名=聚合函数(‘列’))
    • 用法步骤:

      1. 通过先用查询结果Entry.object.value. 查找查询要分组聚合的列
        • Entry.object.value(‘列1’, ‘列2’)
        • 如:
          pub_set = models.Book.objects.values('pub')
          print(books)  # <QuerySet [{'pub': '清华大学出版社'}, {'pub': '清华大学出版社'}, {'pub_hou {'pub': '机械工业出版社'}, {'pub': '清华大学出版社'}]>
          
          
      2. 通过返回结果的 QuerySet.annotate 方法分组聚合得到分组结果
        • QuerySet.annotate(名=聚合函数(‘列’))
        • 返回 QuerySet 结果集,内部存储结果的字典
        • 如:
          pub_count_set = pub_set.annotate(myCount=Count('pub'))
          print(pub_count_set)  # <QuerySet [{'pub': '清华大学出版社', 'myCount': 7}, {'pub': '机械工业出版社', 'myCount': 3}]>
          
      • .values(‘查询列名’)
    • 示例:

      • 得到哪儿个出版社共出版多少本书
      def test_annotate(request):
         - from django.db.models import Count
          from . import models
      
          # 得到所有出版社的查询集合QuerySet
          pub_set = models.Book.objects.values('pub')
          # 根据出版社查询分组,出版社和Count的分组聚合查询集合
          pub_count_set = pub_set.annotate(myCount=Count('pub'))  # 返回查询集合
          for item in pub_count_set:
              print("出版社:", item['pub'], "图书有:", item['myCount'])
          return HttpResponse('请查看服务器端控制台获取结果')
      

F对象

  • 一个F对象代表数据库中某个字段的信息
  • F对象通常是对数据库中的字段值在不加载到内存中的情况下直接在数据库服务器端进行操作
  • F对象在 数据包 django.db.models 中.使用时需要通过如下语句进行加载
    • from django.db.models import F
  1. 作用:

    • 在执行过程中获取某列的值并对其直接进行操作
    • 当同时对数据库中两个字段的值进行比较获取 QuerySet 数据集时,可以便用F对象
  2. 说明:

    • 一个 F()对象代表了一个model的字段的值
  3. 使用它就可以直接参考model的field和执行数据库操作而不用再把它们(model field)查询出来放到python内存中。

  4. 语法:

    from django.db.models import F
    F('列名')
    
  5. 示例1

    • 更新Book实例中所有的制场价涨10元
    models.Book.objects.all().update(market_price=F('market_price')+10)
    # 以下做法好于如下代码
    books = models.Book.objects.all()
    for book in books:
        book.update(market_price=book.marget_price+10)
        book.save()
    
  6. 示例2

    • 对数据库中两个字段的值进行比较,列出哪儿些书的零售价高于定价?
    from django.db.models import F
    from bookstore import models
    books = models.Book.objects.filter(market_price__gt=F('price'))
    for book in books:
        print(book.title, '定价:', book.price, '现价:', book.market_price)
    

Q对象 - Q()

  • 当在获取查询结果集 使用复杂的逻辑或 | 、 逻辑非 ~ 等操作时可以借助于 Q对象进行操作
  • 如: 想找出定价低于20元 或 清华大学出版社的全部书,可以写成
    models.Book.objects.filter(Q(price__lt=20)|Q(pub="清华大学出版社"))
    
  • Q对象在 数据包 django.db.models 中。需要先导入再使用
    • from django.db.models import F
  1. 作用
    • 在条件中用来实现除 and(&) 以外的 or(|) 或 not(~) 操作
  2. 运算符:
    • & 与操作
    • | 或操作
    • 〜 非操作
  3. 语法
    from django.db.models import Q
    Q(条件1)|Q(条件2)  # 条件1成立或条件2成立
    Q(条件1)&Q(条件2)  # 条件1和条件2同时成立
    Q(条件1)&~Q(条件2)  # 条件1成立且条件2不成立
    ...
    
  4. 示例
    from django.db.models import Q
    # 查找清华大学出版社的书或价格低于50的书
    models.Book.objects.filter(Q(market_price__lt=50) | Q(pub_house='清华大学出版社'))
    # 查找不是机械工业出版社的书且价格低于50的书
    models.Book.objects.filter(Q(market_price__lt=50) & ~Q(pub_house='机械工业出版社'))
    

猜你喜欢

转载自blog.csdn.net/weixin_42218582/article/details/102797068
今日推荐