Django框架—模型层之单表查询

一、模型层之ORM

1.什么是ORM

MVC或者MTV框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动

ORM是“对象-关系-映射”的简称;(Object Relational Mapping,简称ORM),ORM是Django中的一个模型,能够独立出来使用的有另一个模块sqlalchemy。

ORM本质就是将类对象的语法翻译成sql语句的一个引擎,我们需要掌握的就是如何使用ORM,写类对象关系语句。

  • 类对象-->sql-->pymysql-->mysql服务端-->磁盘

2.ORM和原生sql语句对比

 

mysql中的原生sql语句写法

sql中的表
-- 创建表:
CREATE TABLE employee(
    id INT PRIMARY KEY auto_increment ,
    name VARCHAR (20),
    gender BIT default 1,
    birthday DATA ,
    department VARCHAR (20),
    salary DECIMAL (8,2) unsigned,
    );
​
​
-- sql中的表纪录                                                  
-- 添加一条表纪录:                                          
INSERT employee (name,gender,birthday,salary,department)
    VALUES("alex",1,"1985-12-12",8000,"保洁部");               
-- 查询一条表纪录:                                       
SELECT * FROM employee WHERE age=24;                               
-- 更新一条表纪录:                                       
UPDATE employee SET birthday="1989-10-24" WHERE id=1;              
-- 删除一条表纪录:                                        
DELETE FROM employee WHERE name="alex" 
原生SQL语句
python中的模型对象写法
from django.db import models
# python的类
class Employee(models.Model):
     id=models.AutoField(primary_key=True)
     name=models.CharField(max_length=32)
     gender=models.BooleanField()
     birthday=models.DateField()
     department=models.CharField(max_length=32)
     salary=models.DecimalField(max_digits=8,decimal_places=2)
​
# python的类对象
# 添加一条表纪录:
emp=Employee(name="alex",gender=True,birthday="1985-12-12",epartment="保洁部")
emp.save()
​
# 查询一条表纪录:
Employee.objects.filter(age=24)
​
# 更新一条表纪录:
Employee.objects.filter(id=1).update(birthday="1989-10-24")
​
# 删除一条表纪录:
Employee.objects.filter(name="alex").delete()
python中的ORM对象

3.settings配置数据库

配置连接的数据库(Mysql)

在settings文件找到DATABASES,注释掉默认的配置,添加你需要连接的mysql数据库。

具体配置参考如下;

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 指定存储数据库
        'NAME': 'day057_single_table_lesson',  # 指定连接的数据库名
        'USER': 'root',  # 用户名
        'PASSWORD': '123',  # 密码
        'HOST': 'localhost',  # 数据库主机
        'PORT': 3306,  # 数据库端口
    }
}

修改数据库驱动

在Django中的默认是使用的是自带的db.sqlite3数据库,用户名和密码也是自动创建的,如果我们需要使用mysql数据库,需要先创建mysql数据库,并激活。

然后启动项目,发现会报错no module named MySQLdb 。这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb 对于py3有很大问题,所以我们需要的驱动是PyMySQL,只需要在项目名文件下的__init__总写入:

import pymysql
pymysql.install_as_MySQLdb()

可视化插件

如果我们需要在pycharm中更加直观的查看我们的表结构和表数据,可以在pycharm安装mysql的可视化插件,安装方法如下图,点开后有个download字样,点击安装即可。

配置完这些,就可以愉快的连接mysql数据库玩耍了。

 

二、单表操作

1.创建模型

在项目下创建一个名为app01的应用;

然后在app01下的models.py中创建模型;

from django.db import models
# Create your models here.

class Book(models.Model):  # 创建一个book类
    id = models.AutoField(primary_key=True)  # 如果表里面没有写主键,表里面会自动生成一个自增主键字段,叫做id字段,orm要求每个表里面必须要写一个主键
    title = models.CharField(max_length=32)  # 和varchar(32)是一样的,32个字符
    pub_date = models.DateField()  # 必须存这种格式"2018-12-12"
    price = models.DecimalField(max_digits=8, decimal_places=2)  # max_digits最大位数,decimal_places小数部分占多少位
    author = models.CharField(max_length=20,null=True)

2.ORM中的字段和参数

ORM中的字段和mysql中是对应的,每个字段有一些特有的参数,参数使用来限制字段,常用的字段和参数

常用简单字段

  • charField:字符串字段, 用于较短的字符串.

    • CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.

  • IntegerField:用于保存一个整数.

  • FloatField:一个浮点数.

    • 必须提供两个参数:max_digits:总位数(不包括小数点和符号);decimal_places:小数位数;

  • AutoField:一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段;

  • booleanField:一个表示真或者假的字段

  • TextField:一个带有检查Email合法性的 CharField,不接受 maxlength 参数.

  • DateField:一个日期字段. 共有下列额外的可选参数:

    • 参数:Argument:描述;auto_now:当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳;

  • DateTimeField:一个日期时间字段. 类似 DateField 支持同样的附加选项.

  • ImageField:类似 FileField, 不过要校验上传对象是否是一个合法图片。

    • 两个可选参数:height_field和width_field,限制图片的高度和宽度

  • FileField:一个文件上传字段. 要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径。

    注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
        1.在你的settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件.(出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对WEB服务器用户帐号是可写的.
        2.在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT).出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField叫作 mug_shot, 你就可以在模板中以 {{object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.
    FileField注意事项
  • URLField:用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且没有返回404响应)。

  • NullBooleanField: 类似 BooleanField, 不过允许 NULL 作为其中一个选项.。推荐使用这个字段而不要用 BooleanField 加 null=True 选项。

更多约束参数

  • null:指定字段是否可为空,默认是False

  • blank:如果为True,该字段允许不填。默认为False。注意与null的区别,两者的范畴不一致,null是数据库范畴的,而blank是orm中数据验证范畴的。

  • default:字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值。

  • primary_key:设置主键,如果为True,那么这个字段就是模型的主键。

  • 如果你没有指定任何一个字段的primary_key=True,Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,否则没必要设置任何一个字段的primary_key=True。

  • unique:如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的

  • choices:由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。

    如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices 中的选项。

  • db_index:如果db_index=True 则代表着为此字段设置数据库索引。

choices字段约束补充

当我们使用choices字段时,是通过元组的形式来指定选择框的提交值和展示值。

如models中定义一个类

class Student(models.Model):

    name = models.CharField(max_length=12,null=True)
    sex_choice = ((1,''),(2,''),)  # 1,2是提交后台的值,男,女是展示给用户看的值

    sex = models.IntegerField(
        choices=sex_choice,
    )

在视图函数中使用

def test(request):

    stu_obj = models.Student.objects.get(name='ryxiong')  # 获取一个学生对象
    print(stu_obj .sex)  # 1,直接查看数据库中学生的性别是1
    print(stu_obj .get_sex_display())  # 男,通过这个方法可以查到对应的显示文本,方便前端展示数据
    print(stu_obj .name)  # ryxiong

    return render(request,'testchoice.html',{'stu_obj ':stu_obj })

模板文件中显示

<p>性别:{{ new_obj.get_sex_display }} </p> <!--没有参数的方法,可以使用万能的句点号调用,展示学生的性别-->

时间字段的独有约束

对于DatetimeField、DateField、TimeField这个三个时间字段,都可以设置如下属性

  • auto_now_add:配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

  • auto_now:配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。

3.同步指令

写完models中的代码后,需要通过两条数据库迁移指令在指定的数据库中创建表。

makemigrations命令

python manage.py makemigrations  # 生成记录,每次修改了models里面的内容或者添加了新的app,新的app里面写了models里面的内容,都要执行这两条

makemigrations命令用来将models中的创建代码语句提交到migrations文件中生成对应的脚本文件,第一次提交会生成一个名为0001_initial.py的初始化文件,之后的每一次更新执行makemigrations命令都会将更新的操作更新到一个新的文件中,如0002_book_author.py。

migrate命令

python manage.py migrate  #执行上面这个语句的记录来创建表,生成的表名字前面会自带应用的名字,例如:你的book表在mysql里面叫做app01_book表

migrate命令会翻译migrations中文件的语句,然后连接到数据库,执行对应的sql语句创建表;

注意:每一次执行migrations中的文件时,都会在django_migrations表中记录,当我们再次执行migrate命令,Django会查看这个记录表,如果发现执行的命令在记录中存在,说明该命令已经被执行过了,不会再被执行。

所以当我们需要重新初始化数据库中的表结构,不仅仅需要删除表名,还需要删除django_migrations中对应的执行记录。

另外我们可以通过pycharm的功能来执行manage.py相关指令。

执行这里,我们会调到Django环境的命令行,在里面直接运行makemigrations和migrate命令就行。

几个注意事项

注意点1:配置应用名称

确保配置文件中的INSTALLED_APPS中写入我们创建的app名称

INSTALLED_APPS = [
    'django.contrib.admin',  # 这是django提供的一些特殊功能的配置(应用,只是咱们看不到),执行同步指令,django会到这里来找到应用的models创建各个应用的表
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "book"  # 直接写app的名字也行,写'app01.apps.App01Config'也行
]

注意点2:mysql版本兼容问题

如果报如下错误

django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required; you have 0.7.11.None

MySQLclient目前只支持到python3.4,因此如果使用的更高版本的python,需要修改如下:

通过查找路径C:\Programs\Python\Python36-32\Lib\site-packages\Django-2.0-py3.6.egg\django\db\backends\mysql,这个路径里的文件把下面代码注释掉就OK了。

if version < (1, 3, 3):
     raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)

注意点3:设置显示对应sql语句

如果想打印orm转换过程中执行的对应sql语句,需要在settings中进行如下配置:

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

另一种查看orm代码对应的sql语句方式

from app01 import models
​
def add_book(request):
    '''
    添加表记录
    :param request: http请求信息
    :return:
    '''
    book_obj = models.Book(title='python',price=123,pub_date='2012-12-12',publish='人民出版社')
    book_obj.save()
    from django.db import connection  # 通过这种方式也能查看执行的sql语句
    print(connection.queries)
    return HttpResponse('ok')

注意点4:mysql严格模式设置

mysql严格模式可以严格控制输入数据库数据的安全性,我们知道在mysql客户端设置严格模式只需要在mysql环境中执行

select @@sql_mode;  --查看当前mysql的模式
set sql_mode="STRICT_TRANS_TABLES" --设置mysql为严格模式,暂时性的。

那么在Django中如何设置mysql的严格模式呢,其实也很简单,只需要在settings配置数据库为mysql的配置中加上一条选项数据就可以了。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': "book_manage1",
        "HOST":"127.0.0.1",
        "PORT":3306,
        "USER":"root",
        "PASSWORD":"123",
        "OPTIONS":{
            "init_command":"set sql_mode='STRICT_TRANS_TABLES'",
        }  # 设置mysql为严格模式
    }
}

三、单表操作值添加表记录

在python中orm的对应关系有三种:

  • 类 ---------->表

  • 类对象 ---------->行(记录)

  • 类属性 ---------->表的字段(重点)

首先想操作表的增删改查,你需要导入这个表,定义对应函数,通过url访问执行这个函数,如这个例子中我们定义operate函数

# urls.py文件
urlpatterns = [
    url(r'^operate/', views.operate),
]
​
# views.py文件
def operate(request):
    """这里写相关对表的操作"""
    # 如添加、删除、修改、查询代码

1.添加单条表记录

方式一:用的少

book_boj = models.Book(title="红楼梦",pub_date="2012-12-12",price=500,author="曹雪芹")  # pub_date=datetime.date.today()这种方式设置时间数据也可以。
# 实例化一个对象表示一行记录
book_boj.save()  # 这个命令就是执行pymysql中的commit命令

方式二:用的多

book_obj = models.Book.objects.create(title="蝶恋花",pub_date="1856-12-6",price=200,author="晏殊")
# create方法的返回值book_obj就是插入book表中的蝶恋花这本书籍纪录对象
# Book.objects就像book表的管理器,提供了增删改查的所有方法

2.批量添加表记录

使用bulk_create方法批量添加列表中的对象

import random
    # 方式3:批量插入
    book_list = []
    for i in range(10):
        bk_obj = models.Book(
            title='枉凝眉%s'%i,
            pub_date='1846-7-2%s'%(random.randint(0,9)),
            price=random.randint(80,200),
            author="一只熊%s"%i
        )
        book_list.append(bk_obj)
​
    models.Book.objects.bulk_create(book_list)  # 使用bulk_create方法批量添加数据,效率比for循环添加高

3.update_or_create方法

update_or_create方法,有就更新,没有就创建

obj, created = models.Book.objects.update_or_create(
    id=3,  # 查找筛选条件
    defaults={  # 更新或添加的数据,有就更新,没有就添加
        "title": "红楼梦(下)",
        "pub_date": "1826-10-8",
        "price": 250,
    }
)

执行所有插入语句后的表结构如下

mysql> select * from app01_book;
+----+--------------------+------------+--------+------------+
| id | title              | pub_date   | price  | author     |
+----+--------------------+------------+--------+------------+
|  1 | 红楼梦             | 2012-12-12 | 500.00 | 曹雪芹     |
|  2 | 蝶恋花             | 1856-12-06 | 200.00 | 晏殊       |
|  3 | 红楼梦(下)       | 1826-10-08 | 250.00 | 曹雪芹     |
|  4 | 蝶恋花             | 1856-12-06 | 200.00 | 晏殊       |
|  5 | 枉凝眉0            | 1846-07-29 | 124.00 | 一只熊0    |
|  6 | 枉凝眉1            | 1846-07-21 | 147.00 | 一只熊1    |
|  7 | 枉凝眉2            | 1846-07-23 | 127.00 | 一只熊2    |
|  8 | 枉凝眉3            | 1846-07-29 |  92.00 | 一只熊3    |
|  9 | 枉凝眉4            | 1846-07-22 | 187.00 | 一只熊4    |
| 10 | 枉凝眉5            | 1846-07-29 | 142.00 | 一只熊5    |
| 11 | 枉凝眉6            | 1846-07-21 | 132.00 | 一只熊6    |
| 12 | 枉凝眉7            | 1846-07-25 | 191.00 | 一只熊7    |
| 13 | 枉凝眉8            | 1846-07-28 | 188.00 | 一只熊8    |
| 14 | 枉凝眉9            | 1846-07-22 | 141.00 | 一只熊9    |
+----+--------------------+------------+--------+------------+
14 rows in set (0.00 sec)
添加数据后的Book表结构

四、单表操作之查询表(重点)

model中的表类有一个objects属性,这个objects就好像一个管理器,提供了所有的增删改查方法,下面是常用的查询方法。

注意:model对象和queryset对象区别

  • model对象就是表中某一行数据对应的数据模型

  • queryset类型是django中的数据类型,里面存放了model对象,可以为空

1.常用查询方法

all()

查询所有的对象结果,返回一个queryset类型,包含所有的model对象

bk_obj = models.Book.objects.all()  # 查询所有结果
print(bk_obj)
# <QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>]>

注意:如果想显示时,显示特定的特征字段,便于查看,可以在book类中定义__str__方法。

def __str__(self):
    return str(self.id) +"." + self.title

filter(**kwargs)

查询满足筛选条件的model对象结果,返回一个queryset类型。

有多个条件使用逗号分隔,条件之间是and的关系,这里无法实现or的关系

bk_obj = models.Book.objects.filter(title="红楼梦",price=500)
​
print(bk_obj)
# <QuerySet [<Book: 1.红楼梦>]>

get(**keargs)

查询满足筛选条件的model对象,返回model对像,也就是行记录

注意:

  • get的查询结果有且只有一个。

  • 多余一个报错:get() returned more than one Book -- it returned 3!

  • 没有也报错:Book matching query does not exist.

bk_obj = models.Book.objects.get(title="枉凝眉1")
print(bk_obj)  # 6.枉凝眉1,这里返回的是model对象,行记录

exclude(**kwargs)

查询排除了满足筛选条件的所有结果对象,返回一个queryset类型

参数可以为多个,排除满足任意筛选条件的对象

bk_obj = models.Book.objects.exclude(title="蝶恋花",price=127)
print(bk_obj)
# <QuerySet [<Book: 1.红楼梦>, <Book: 2.蝶恋花>, <Book: 3.红楼梦(下)>, <Book: 4.蝶恋花>, <Book: 5.枉凝眉0>, <Book: 6.枉凝眉1>, <Book: 7.枉凝眉2>, <Book: 8.枉凝眉3>, <Book: 9.枉凝眉4>, <Book: 10.枉凝眉5>, <Book: 11.枉凝眉6>, <Book: 12.枉凝眉7>, <Book: 13.枉凝眉8>, <Book: 14.枉凝眉9>]>

order_by(*field)

由queryset类型的对象来调用,对查询的结果排序,默认按照id的升序,返回仍是queryset类型。

排序默认是升序,如果需要降序,在字段前面添加"-"即可。

bk_obj = models.Book.objects.filter(author="曹雪芹").order_by("-id","price")  # 查询作者为“曹雪芹”的书籍,按照id的降序,价格的升序排列
print(bk_obj)
# <QuerySet [<Book: 3.红楼梦(下)>, <Book: 1.红楼梦>]>

reverse()

只能有order_by查询返回的queryset类型对象调用,对查询的结果反转。

bk_obj = models.Book.objects.filter(author="曹雪芹").order_by("-id","price").reverse()
print(bk_obj)
# <QuerySet [<Book: 1.红楼梦>, <Book: 3.红楼梦(下)>]>

count()

由queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。

bk_obj = models.Book.objects.filter(author="曹雪芹").count()
print(bk_obj)  # 2

first()

由queryset类型的数据来调用,返回第一个model对象,也就是第一条记录。等效于索引取值[0]

bk_obj = models.Book.objects.filter(author="曹雪芹").first()
print(bk_obj) # 1.红楼梦 等效于取索引[0]

last()

由queryset类型的数据来调用,返回最后一条记录

exists()

由queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False

bk_obj = models.Book.objects.filter(author="曹雪芹").exists()
print(bk_obj)  # True

注意exists与直接对结果判断的区别

  • exists是取查询结果的第一条来判断是否有值,效率高

  • 直接判断结果,会遍历所有查询结果,效率低

values(*field) ***

较常用,由queryset类型的对象来调用,返回一个ValueQuerySet对象,一个特殊的queryset,结果是一个可迭代的列表嵌套字典序列

只要是返回queryset类型的对象,就可以继续链式调用queryset对象的其他查找方法。

bk_obj = models.Book.objects.filter(author="曹雪芹").values("id","title")
print(bk_obj)
# <QuerySet [{'id': 1, 'title': '红楼梦'}, {'id': 3, 'title': '红楼梦(下)'}]>

values_list(*field)

与values()非常相似,只不过values_list返回的是一个列表嵌套元组序列,values返回列表嵌套字典序列

bk_obj = models.Book.objects.filter(author="曹雪芹").values_list("id", "title")
print(bk_obj)
# <QuerySet [(1, '红楼梦'), (3, '红楼梦(下)')]>

distinct()

对values()和values_list()方法得到的queryset类型数据去重。

注意:

如果表中没有主键,django也会默认生成id为主键,所以我们直接对所有查询结果去重是毫无意义的。

all_books = models.Book.objects.all().distinct()  # 不会有重复项

使用方法

bk_obj = models.Book.objects.all().values_list("title","price").distinct()  # title和price两个同时重复才算一条重复的记录
print(bk_obj)  # 结果中蝶恋花被去重了

小结

只有get、first、last方法拿到的是一个model对象,其他方法拿到的都是queryset类型。

2.基于双下滑线的模糊查询

filter条件中的模糊查询

使用双下划线对条件中的字段进行条件约束

语法:字段名__模糊条件

models.Book.objects.filter(price__in=[250,500])  # price值等于这三个里面的任意一个的对象
models.Book.objects.filter(price__gt=100)  # bigthan,大于,大于等于是price__gte=100,别写price>100,这种参数不支持
models.Book.objects.filter(price__lt=100)  # smallthan,小于
models.Book.objects.filter(price__range=[100,200])  # sql的between and,大于等于100,小于等于200
models.Book.objects.filter(title__contains="红楼")  # title值中包含“红楼”字样
models.Book.objects.filter(title__icontains="python")  # 不区分大小写
models.Book.objects.filter(title__startswith="")  # 以什么开头;istartswith,不区分大小写
models.Book.objects.filter(pub_date__year=2012)  # 日期数据年份是2012的

关于日期查询

models.Book.objects.filter(pub_date__year=2012)  # 年份为2012
models.Book.objects.filter(pub_date__year__gt=2012)  # 年份大于2012
models.Book.objects.filter(pub_date__year=2019, pub_date__month=2)  # 年份为2019,月份为2月

五、单表操作之删除记录

python中删除一条记录的方法是delete(),而删除记录的调用者可以是一个model对象,也可以是一个queryset集合。

delete运行时会立即删除对象,没有任何返回值。

1.两种对象调用delete

1.model对象调用删除方法,会删除单个model对象

bk_obj = models.Book.objects.get(id=14)  # 找到model对象
bk_obj.delete()
print(bk_obj)  # <QuerySet []>

2.queryset类型调用删除方法,可以一次删除queryset中的所有对象

bk_obj = models.Book.objects.filter(id__in=[13,14])
bk_obj.delete()
print(bk_obj)  # <QuerySet []>

2.关于联级删除

如果涉及到外键,django中的外键会默认设置联级关系,on delete cascade;也就是说删除一个对象会删除与它相关的外键对象。

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

delete() 方法是 QuerySet 上的方法,但并不适用于 Manager 本身。这是一种保护机制,是为了避免意外地调用 Entry.objects.delete() 方法导致 所有的 记录被误删除。

如果你确认要删除所有的对象,那么你必须显式地调用;

Entry.objects.all().delete()

如果不想联级删除,可以在settings中设置

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

六、单表操作之修改记录

update()

models中修改表记录使用update方法;

update方法只能由queryset类型的对象调用,意思是你可以同时更新多条记录,update方法会返回一个整型数值,表示收到影响的记录条数。

bk_obj= models.Book.objects.filter(title__startswith="蝶恋").update(price=150)  # 更新所有名字以“蝶恋”开头的数据价格为150
print(bk_obj)  # 2

注意

type = "date" 的input标签,value的值必须是'Y-m-d'的格式,这个标签才能认识并被赋值,所以,要通过date过滤给它改变格式。

<input type="date" class="form-control" id="book_pub_date" placeholder="出版日期" name="book_pub_date" value="{{ edit_obj.pub_date|date:'Y-m-d' }}">

 

posted @ 2019-05-22 21:49  ryxiong728  阅读(495)  评论(0编辑  收藏  举报