PYTHON3.Django_day03(见pdf)

day02 回顾
   请求 HttpRequest 和响应 HttpResponse
     def xxx_view(request):
         if request.method == "GET":
            return HttpResponse("GET")
         elif request.method == 'POST':
             return HttpResponse("POST")

  get请求:
     request.GET (QueryDict类型的字典)
     request.GET['key']
     request.GET.get('key', 默认值)
     request.GET.getlist('key')
   post 请求
     request.POST (QueryDict类型的字典)
     request.POST['key']
     request.POST.get('key', 默认值)
     request.POST.getlist('key')
     post请求要提交成功需要注释掉 CsrfViewMiddleware

Django遵循的设计模式
    MTV
      M-model
      T-template
      V-view

模板:
   动态的html
   配置模板
     settings.py
     TEMPLATES = [
       {
         DIRS = [os.path.join(BASE_DIR, 'templates')]
       }
     ]
     模板的加载
     def xxx_view(request):
         return render(request, 'xxx.html', locals())

    def xxx_view(request):
         t = loader.get_template('xxx.html')
         html = t.render(locals())
         return HttpResponse(html)

模板的变量:
    {{ 变量名 }}
    {{ 变量名.列表的索引 }}
    {{ 变量名.字典的键 }}
    {{ 函数名 }}
    {{ 对象.方法名 }}
模板的if 标签
     {% if xxxx %}
       ...
     {% elif yyyy %}
       ...
     {% else %}
        ...
     {% endif %}

模板的 for 标签
     {% for 变量 in 可迭代对象 %}
        ...
     {% empty %}
        ...
     {% endfor %}
   内置变量forloop
        forloop.counter0
        forloop.counter
        forloop.revcounter
        forloop.revcounter0
        forloop.first
        ...
模板的注释
   {#    #}
   {% comment %}
     ...
   {% endcomment %}
过滤器
   {{ mystr | upper }}

模板的继承
   myfile.html
   <html>
   ....
      {% block name1 %}
         <h1>父模板的内容 </h1>
      {% endblock name1 %}
      {% block name2 %}
         <h1> 标题1 </h1>
      {% endblock name2 %}
   </html>

  # myfile2.html
   {% extends 'myfile.html' %}
      {% block name2 %}
         <h1> 标题2 </h1>
      {% endblock name2 %}

url 反向解板
    url(r'^xxx', xxx_view, name='xxx')
    url(r'^yyy(\d+)(\w+)', yyy_view, name='yyy')
   模板中
     {% url 'xxx' %}
     {% url 'yyy' '123' 'tedu'}
     /yyy123tedu


day3笔记
静态文件
    https://www.baidu.com/img/bd_logo1.png
路由地址(url地址):
     /img/bd_logo1.png

存储位置
     /home/tarena/django/day3/code/bd_logo1.png

示例:
   路由:
     /static/images/meinv.png
   存储位置
     /home/tar.../mysite3/static/images/meinv.png

路由
127.0.0.1:8000/show_image


mysql 数据
   mysql -u root -p123456

  用户名: root
   密码: 123456
   IP地址: 127.0.0.1
   端口号: 3306
   数据库名: 'mysite3_db'

  sql> create database mysite3_db default charset utf8 collate utf8_general_ci;

        create database mysite3_db default charset utf8 collate utf8_general_ci;


练习:
    在bookstore/models.py 中再加入下个模型类
    class Author(....):
           # 姓名
           name = ...
           # 年龄
           age = .....
           # 其它自己尝试
     运行迁移,查看数据库的变量
     ----------------------------------------------------------------------------------------------------------------------------


# 《Django 教程》
  - 讲师: 魏明择
  - 时间: 2019

## 目录
<!-- TOC depthFrom:3 depthTo:5 -->

- [静态文件](#静态文件)
- [Django中的应用 - app](#django中的应用---app)
     - [创建应用app](#创建应用app)
     - [应用的分布式路由](#应用的分布式路由)
         - [django.conf.urls 里的include 函数](#djangoconfurls-里的include-函数)
- [数据库 和 模型](#数据库-和-模型)
     - [Django下使用mysql数据库](#django下使用mysql数据库)
- [模型(Models)](#模型models)
- [Python 数据库模型 - Models](#python-数据库模型---models)
     - [字段选项](#字段选项)
     - [数据库迁移的错误处理方法](#数据库迁移的错误处理方法)
- [数据库的操作(CRUD操作)](#数据库的操作crud操作)
     - [管理器对象](#管理器对象)
     - [创建数据对象](#创建数据对象)
     - [Django shell 的使用](#django-shell-的使用)
         - [查询数据](#查询数据)

<!-- /TOC -->

### 静态文件
<!-- 改进版需要添加静态文件的配置步骤... -->
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. 示例:
         ```py
         # file: setting.py
         STATICFILES_DIRS = [
             os.path.join(BASE_DIR, "static")
         ]
         ```
3. 访问静态文件
     1. 使用静态文件的访问路径进行访问
         - 访问路径: STATIC_URL=/static/

         -  示例:
             ```py
             <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' %}">
     - 示例:
         - 路由配置文件
         ```py
         # 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
         <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>
         ```
     - 练习:
         ```
         1. 127.0.0.1:8000 : 显示首页效果
         2. 127.0.0.1:8000/login : 显示登录页
         处理好所有的静态文件
         ```
     <!--
     - 练习:
         ```
         石头剪刀布游戏?
         ```
      -->

### Django中的应用 - app
- 应用在Django项目中是一个独立的业务模块,可以包含自己的路由,视图,模板,模型

####  创建应用app
- 创建步骤
     1. 用manage.py 中的子命令 startapp 创建应用文件夹
     2. 在settings.py 的 INSTALLED_APPS 列表中配置安装此应用

- 创建应用的子命令
     - 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 中配置应用, 让此应用能和整个项目融为一体
         ```py
         # file : settings.py
        INSTALLED_APPS = [
             ... ...,
             '自定义应用名称'
         ]

        ```
     - 如:
         ```py
         INSTALLED_APPS = [
             # ....
             'user',  # 用户信息模块
             'music',  # 收藏模块
         ]
         ```

#### 应用的分布式路由
- Django中,主文件夹可以不处理用户具体请求的,主文件夹的作用是做项目的初始化以及请求的分发(分布式请求处理)。具体的请求可以由应用来进行处理的
- 如图:
     - ![](images/urls.png)
##### django.conf.urls 里的include 函数
- 作用:
     - 用于分发将当前路由转到模个模块的 urlpatterns 进行分布式处理
- 函数格式
     - include('App命字.url模块名')
- 参数说明:
     - 模块`App命字/url模块名.py` 文件件里必须有urlpatterns 列表

- 使用 include 函数让某个正则匹配后关联分支到某个app示例如下:
```py
# file : <项目名>/urls.py
from django.conf.urls import include

urlpatterns = [
     url(r'^admin/', admin.site.urls),
     url(r'^music/', include('music.urls')),
]
```
```py
# file : music/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),
     # ...
]
```
- 练习:
     ```
     1.创建四个应用
         1.创建 index 应用,并注册
         2.创建 sport 应用,并注册
         3.创建 news  应用,并注册
         4.创建 music 应用,并注册
     2.创建分布式路由系统
         主路由配置只做分发
         每个应用中处理具体访问路径和视图
         1. 127.0.0.1:8000/music/index
             交给 music 应用中的 index_view() 函数处理
         2. 127.0.0.1:8000/sport/index
             交给 sport 应用中的 index_view() 函数处理
         3. 127.0.0.1:8000/news/index
             交给 news  应用中的 index_view() 处理处理
     ```

### 数据库 和 模型
#### 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;`
         ```sql
         create database mywebdb default charset utf8 collate utf8_general_ci;
         ```
     2. 数据库的配置
         - sqlite 数据库配置
         ```
         # file: settings.py
         DATABASES = {
             'default': {
                     'ENGINE': 'django.db.backends.sqlite3',
                     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
             }
         }
         ```
         - mysql 数据库配置
         ```py
         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'`
     3. 添加 mysql 支持
         - 安装pymysql 模块
             - `$ sudo pip install pymysql`
         - 修改项目中__init__.py 加入如下内容来提供pymysql引擎的支持
             ```py
             import pymysql
             pymysql.install_as_MySQLdb()
             ```

3. 数据库的迁移
     - 迁移是Django同步您对模型所做更改(添加字段,删除模型等) 到您的数据库模式的方式
     1. 生成或更新迁移文件
         - 将每个应用下的models.py文件生成一个中间文件,并保存在migrations文件夹中
         - `python3 manage.py makemigrations`
     2. 执行迁移脚本程序
         - 执行迁移程序实现迁移。将每个应用下的migrations目录中的中间文件同步回数据库
         - `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
         ```shell
         $ python3 manage.py startapp bookstore
         ```
     - 添加模型类并注册app
         ```py
         # file : bookstore/models.py
         from django.db import models

        class Book(models.Model):
             title = models.CharField("书名", max_length=50, default='')
             price = models.DecimalField('定价', max_digits=7, decimal_places=2, default=0.0)
         # file : setting.py
         INSTALLED_APPS = [
             ...
             'bookstore',
         ]
         ```
     - 生成迁移脚本文件`bookstore/migrations/0001_initial.py`并进行迁移
         ```shell
         $ 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 下的文件是自动生成的迁移脚本文件,可以手动删除且在下一次迁移时自动生成

<!--
     - 使用Django 的 sqlmirate子命令 查看迁移脚本的 执行的SQL语句
     ```shell
     # 命令格式: python3 manage.py sqlmigrate app名称 迁移脚本编号0001
     $ python3 manage.py sqlmigrate bookstore 0001
     BEGIN;
     --
     -- Create model Book
     --
     CREATE TABLE `bookstore_book` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(50) NOT NULL, `price` double precision NOT NULL);
     COMMIT;
     $
     ```
  -->

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

3. 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,
                 default=0.0
             )
             ```
     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
         - 作用:表示不定长的字符数据
     - 参考文档 <https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-types>

#### 字段选项
4. FIELD_OPTIONS
     - 字段选项, 指定创建的列的额外的信息
     - 允许出现多个字段选项,多个选项之间使用,隔开
     1. primary_key
         - 如果设置为True,表示该列为主键,如果指定一个字段为主键,则此数库表不会创建id字段
     2. blank
         - 设置为True时,字段可以为空。设置为False时,字段是必须填写的。字符型字段CharField和TextField是用空字符串来存储空值的。 默认值是False。
     3. null
         - 如果设置为True,表示该列值允许为空。日期型、时间型和数字型字段不接受空字符串。所以设置IntegerField,DateTimeField型字段可以为空时,需要将blank,null均设为True。
         - 默认为False,如果此选项为False建议加入default选项来设置默认值


     4. default
         - 设置所在列的默认值,如果字段选项null=False建议添加此项
     5. db_index
         - 如果设置为True,表示为该列增加索引
     6. unique
         - 如果设置为True,表示该字段在数据库中的值必须是唯一(不能重复出现的)
     7. db_column
         - 指定列的名称,如果不指定的话则采用属性名作为列名
     8. verbose_name
         - 设置此字段在admin界面上的显示名称。
     - 示例:
         ```py
         # 创建一个属性,表示用户名称,长度30个字符,必须是唯一的,不能为空,添加索引

        name = models.CharField(max_length=30, unique=True, null=False, db_index=True)
         ```
- 文档参见:
     - <https://docs.djangoproject.com/en/1.11/ref/models/fields/#field-options>

- 示例:



#### 数据库迁移的错误处理方法
- 当执行 `$ 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


### 数据库的操作(CRUD操作)
- CRUD是指在做计算处理时的增加(Create)、读取查询(Read)、更新(Update)和删除(Delete)

#### 管理器对象
- 每个继承自 models.Model 的模型类,都会有一个 objects 对象被同样继承下来。这个对象叫管理器对象
- 数据库的增删改查可以通过模型的管理器实现
     ```
     class Entry(models.Model):
         ...
     Entry.objects.create(...) # 是管理器对象
     ```

#### 创建数据对象
- Django 使用一种直观的方式把数据库表中的数据表示成Python 对象
- 创建数据中每一条记录就是创建一个数据对象
     1. Entry.objects.create(属性1=值1, 属性2=值1,...)
         - 成功: 返回创建好的实体对象
         - 失败: 抛出异常
     2. 创建 Entry 实体对象,并调用 save() 进行保存
         ```
         obj = Entry(属性=值,属性=值)
         obj.属性=值
         obj.save()
         无返回值,保存成功后,obj会被重新赋值
         ```
     3. 示例1:
         ```
         try:
             abook = Book.objects.create(title='Python', pub='清华大学出版社')
             print(abook)
         except:
             print('创建对象失败')
         ```
     4. 示例2:
         ```
         try:
             abook = Book(title='Python', pub='清华大学出版社')
             abook.save
             print(abook)
         except:
             print('创建对象失败')
         ```
     5. 示例3:
         ```
         try:
             abook = Book()
             abook.title='Python'
             abook.pub='清华大学出版社'
             abook.save
             print(abook)
         except:
             print('创建对象失败')
         ```

    - 练习:
         - 使用以上三种方式,分别向Book和Publisher表中各增加三条数据

#### Django shell 的使用
- 在Django提供了一个交互式的操作项目叫 `Django Shell` 它能够在交互模式用项目工程的代码执行相应的操作
- 利用 Django Shell 可以代替编写View的代码来进行直接操作
- 在Django Shell 下只能进行简单的操作,不能运行远程调式
- 启动 Django shell 显示IPython风格的交互界面如下:
     ```shell
     $ python3 manage.py shell
     manage.py shell
     Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04)
     Type 'copyright', 'credits' or 'license' for more information
     IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.

    In [1]:
     In [2]: from bookstore import models
     In [3]: models.Book.objects.create(title="Python")
     Out[3]: <Book: Book object>
     In [4]: book = models.Book.objects.create(title='C++')
     In [4]: print(book)
     Book object
     ```

- 练习:
     ```
     在 bookstore/models.py 应用中添加两个model类
     1. Book - 图书
         1. title - CharField 书名,非空,唯一
         2. pub - CharField 出版社,字符串,非空
         3. price - 图书价格,,
         4. market_price - 图书零售价
     2. Author - 作者
         1. name - CharField 姓名,非空,唯一,加索引
         2. age - IntegerField, 年龄,非空,缺省值为1
         3. email - EmailField, 邮箱,允许为空
     ```
     - 然后用Django Shell 添加如下数据
         - 图书信息
             | 书名   | 定价 | 零售价 | 出版社      |
             |---------|-------|--------------|----------------|
             | Python  | 20.00 |        25.00 | 清华大学出版社 |
             | Python3 | 60.00 |        65.00 | 清华大学出版社 |
             | Django  | 70.00 |        75.00 | 清华大学出版社 |
             | JQuery  | 90.00 |        85.00 | 机械工业出版社 |
             | Linux   | 80.00 |        65.00 | 机械工业出版社 |
             | Windows | 50.00 |        35.00 | 机械工业出版社 |
             | HTML5   | 90.00 |       105.00 | 清华大学出版社 |
         - 作者信息:
             | 姓名   | 年龄 | 邮箱 |
             |-------|------|-----|
             | 王老师 | 28 | wangwc@tedu.cn |
             | 吕老师 | 31 | lvze@tedu.cn |
             | 祁老师 | 30 | qitx@tedu.cn |
        


##### 查询数据
- 数据库的查询需要使用管理器对象进行
- 通过 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 子句对查询结果进行根据某个字段选择性的进行排序
     - 说明:
         - 默认是按照升序排序,降序排序则需要在列前增加'-'表示

    - 示例:
         ```py
         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)
         ```

posted @ 2019-07-15 19:21  圣枷  阅读(358)  评论(0编辑  收藏  举报