Django ORM操作

常用字段

models中所有的字段类型其实本质就那几种,整形varchar什么的,都没有实际的约束作用,虽然在models中没有任何限制作用,但是还是要分门别类,对于校验性组件校验非常有用

就比如说邮箱类型,你在输入邮箱的时候如果不按照邮箱格式输入,瞎鸡儿输入会提示你不合法,虽然输入的是字符串,但是不是规定的邮箱字符串

字段 描述
AutoField int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。
IntegerField 一个整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存,)
BigIntegerField
CharField 字符类型对应MySQL的varchar类型,必须提供max_length参数, max_length表示字符长度。
DateField 日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。
DecimalField 10进制小数, max_digits,小数总长度 ,decimal_places,小数位长度
EmailField email字段,内部还是varchar(254)
BooleanField 布尔值,传True或False,自动转成1/0
TextField 存储大段文本
FileField 专门用来存放文件路径,传值的时候,直接传文件对象,将路径保存到数据库
关系字段 描述
ForeignKey 关系字段,外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 '一对多'中'多'的一方。
OneToOneField 一对一字段。
ManyToManyField 多对多表关系并且这一张多对多的关系表是有Django自动帮你建

常用字段参数

参数 描述
null 用于表示某个字段可以为空。
unique 如果设置为unique=True 则该字段在此表中必须是唯一的 。
db_index 如果db_index=True 则代表着为此字段设置索引。
default 为该字段设置默认值。
DateField和DateTimeField 描述
auto_now_add 配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
auto_now 配置上auto_now=True,每次更新数据记录的时候会更新该字段。
关系字段参数 描述
to 设置要关联的表
to_field 设置要关联的表的字段
on_delete 当删除关联表中的数据时,当前表与其关联的行的行为。
db_constraint 是否在数据库中创建外键约束,默认为True。

自定义字段

Django中的CharField对应的MySQL数据库中的varchar类型,没有设置对应char类型的字段,

但是Django允许我们自定义新的字段,下面我来自定义对应于数据库的char类型

自定义字段在实际项目应用中可能会经常用到

from django.db import models

# Create your models here.
#Django中没有对应的char类型字段,但是我们可以自己创建
class FixCharField(models.Field):
'''
自定义的char类型的字段类
'''
def __init__(self,max_length,*args,**kwargs):
self.max_length=max_length
super().__init__(max_length=max_length,*args,**kwargs) def db_type(self, connection):
'''
限定生成的数据库表字段类型char,长度为max_length指定的值
:param connection:
:return:
'''
return 'char(%s)'%self.max_length #应用上面自定义的char类型
class Class(models.Model):
id=models.AutoField(primary_key=True)
title=models.CharField(max_length=32)
class_name=FixCharField(max_length=16)

字段合集和对应关系

我们来创建一张表:

models.py:
class Books(models.Model):
title = models.CharField(max_length=254)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_date = models.DateField() 将表同步到MySQL中:
python3 manage.py makemigrations
python3 manage.py migrate

然后我们在django测试文件中,如果单纯的测试某个py文件,需要手动配置测试脚本

app01/tests.py:
# Create your tests here.
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
import django
django.setup()
from app01 import models
# 下面开始写测试的代码。 # 创建数据------------------------------------------------------------------------
# 1. create 方法
models.Books.objects.create(title='三国演义',price=123,publish_date='2019-11-11') from datetime import date
ctime = date.today()
models.Books.objects.create(title='红楼梦',price=888,publish_date=ctime) # 2. 利用对象的绑定方法创建数据
book_obj = models.Books(title='西游记',price=666,publish_date='2000-11-11')
book_obj.save()
# 插入的数据
# id title price publish_date
# 4 三国演义 123 2019-11-11
# 5 红楼梦 888 2019-11-27
# 6 西游记 666 2000-11-11 # 修改数据------------------------------------------------------------------------
'''
利用filter 自动查询当前表的主键字段,pk代表primary_key
filter查询出来的是一个queryset对象:
只要是queryset的对象就可以无限制的调用queryset的方法
只要是queryset的对象就可以点query查看当前结果内部对应的sql语句
'''
# 1. 利用queryset方法修改数据
models.Books.objects.filter(pk=4).update(price=444)
# 2. 利用对象方法修改数据
book_obj = models.Books.objects.get(pk=1)
book_obj.price = 222
book_obj.save() # 不推荐使用,推荐使用queryset方法
'''
利用对象修改,内部其实是将所有的字段重新写进去
get 和 filter的区别:
filter 获取到的是一个queryset对象,类似于一个列表,没有数据的时候不会报错
get获取到的数据就是数据本身,但是没有数据的时候会报错
''' # 删除数据------------------------------------------------------------------------
# 1. 利用queryset方法 :delete()
models.Books.objects.filter(pk=4).delete()
# 2. 对象的方法
book_obj = models.Books.objects.get(pk=4)
book_obj.delete() # 如果你想直接查看所有的orm语句内部对应的sql语句,可以在配置文件中配置:
settings.py: LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}

单表操作

方法(加括号使用) 描述
all 查询所有,返回QuerySet对象
filter 筛选,相当于原生SQL的where条件,返回QuerySet对象
get 筛选,获取数据对象本身,如果不存在报错,并且查询条件必须是唯一的。
first 取QuerySet对象中第一个数据对象
last 取QuerySet对象中最后一个数据对象
count 统计数据的条数
values 获取数据对象中指定的字段的值,返回列表套字典的QuerySet对象
values_list 获取数据对象中指定的字段的值,返回列表套元组的QuerySet对象
order_by 指定字段进行排序,默认升序,在字段前加-是降序
reverse 颠倒顺序,前提是颠倒的对象必须有顺序,也就是order_by过后的
exclude 查询排除什么之外,返回QuerySet对象
exists 判断查询结果是否有值,返回布尔值
distinct 对指定字段查询出来的结果进行去重操作
# 查询数据 13 条------------------------------------------------------------------------
# 1. all() 查询所有,返回queryset对象
print(models.Books.objects.all()) # 2. filter() 筛选 相当于原生sql语句里面的where关键字,返回queryset对象
print(models.Books.objects.filter(pk=4)) # 3. get() 筛选 获取的数据是对象本身,数据不存在直接报错,并且查询条件必须唯一,返回数据对象本身
print(models.Books.objects.get(pk=4)) # 4. first() 获取queryset对象中第一个数据对象 返回数据对象
print(models.Books.objects.filter(pk=4).first()) # 5. last() 获取queryset对象中最后一个数据对象 返回数据对象
print(models.Books.objects.filter(pk=4).last()) # 6. count() 统计数据的条数 返回数字
print(models.Books.objects.count()) # 7. values() 获取数据对象中指定的字段的值,可以指定多个,返回queryset对象,列表套字典
print(models.Books.objects.values('title','price')) # 8. values_list() 获取数据对象中指定的字段的值,可以指定多个,返回queryset对象,列表套元组
print(models.Books.objects.values_list('title','price')) # 9. order_by() 按照指定的字段排序,默认是升序,在字段前面加 - 是降序
print(models.Books.objects.order_by('pk').values('pk'))
print(models.Books.objects.order_by('-pk').values('pk')) # 10. reverse() 颠倒顺序,前提是颠倒的对象必须有顺序,排序之后的
print(models.Books.objects.order_by('pk').reverse().values('pk')) # 11. exclude() 查询条件排除什么
print(models.Books.objects.exclude(pk=4).values('pk')) # 12. exists() 判断查询结果是否有值,返回的是布尔值
print(models.Books.objects.exists()) # 13. distinct() 对查询结果去重,前提是数据完全相同的情况下
print(models.Books.objects.values('title','price').distinct())

双下划线查询

方法 描述
__gt 字段大于什么什么值
__lt 字段小于什么什么值
__gte 字段大于等于什么值
__lte 字段小于等于什么值
__in 字段是什么或什么的值,or的关系
__range 字段是什么和什么之间的值,btwen..and...
__year 字段的年份是什么什么的值
__month 字段的月份是什么什么的值
# 下划线查询------------------------------------------------------------------------
# 1. 查询价格大于500的书
print(models.Books.objects.filter(price__gt=500).values('title')) # 2. 查询价格小于500的书籍
print(models.Books.objects.filter(price__lt=500).values('title')) # 3. 查询价格大于等于500的书籍
print(models.Books.objects.filter(price__gte=500).values('title')) # 4. 查询价格小于等于500的书籍
print(models.Books.objects.filter(price__lte=500).values('title')) # 5. 查询价格是222 或 444 或 500 的书籍
print(models.Books.objects.filter(price__in=[222,444,500]).values('title')) # 6. 查询价格在200到800之间的书籍 顾头也顾尾
print(models.Books.objects.filter(price__range=(200,800)).values('title')) # 7. 查询出版日期是2019年的书籍
print(models.Books.objects.filter(publish_date__year='2019').values('title')) # 8. 查询出版日期是11月份的书籍
print(models.Books.objects.filter(publish_date__month='11').values('title'))

模糊查询

MySQL中的模糊查询,关键字like,模糊匹配的符号:%_

方法 描述
__startswith 字段的值以什么什么开头的值
__endswith 字段的值以什么什么结尾的值
__contanins 字段的值包含什么什么的值,区分大小写
__icontanins 字段的值包含什么什么的值,不区分大小写
# 模糊查询------------------------------------------------------------------------
# 1. 查询书籍是以三开头的书
print(models.Books.objects.filter(title__startswith='三').values('title')) # 2. 查询书籍是以三结尾的书
print(models.Books.objects.filter(title__endswith='三').values('title')) # 3. 查询书籍名称中包含游字的书籍
print(models.Books.objects.filter(title__contains='游').values('title')) # 4. 查询书籍名称中包含字母p的书籍,区分大小写
print(models.Books.objects.filter(title__contains='p').values('title')) # 5. 查询书籍名称中包含字母p的书籍,区分大小写
print(models.Books.objects.filter(title__icontains='p').values('title'))

多表操作

一对多字段数据的操作

为了方便操作,我们创建图书管理系统相关表来演示多表操作

models.py:

class Book(models.Model):
title = models.CharField(max_length=254)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_date = models.DateField(auto_now_add=True)
'''
auto_now :每次修改数据的时候,会自动更新时间
auto_now_add :当数据创建出来的时候,自动将创建时间记录下来
'''
publish = models.ForeignKey(to='Publish')
authors = models.ManyToManyField(to='Author') class Publish(models.Model):
name = models.CharField(max_length=254)
addr = models.CharField(max_length=254) class Author(models.Model):
name = models.CharField(max_length=254)
email = models.EmailField(max_length=254)
author_detail = models.OneToOneField(to='AuthorDetail') class AuthorDetail(models.Model):
phone = models.BigIntegerField()
add = models.CharField(max_length=254)
# 一对多字段数据的增删改查------------------------------------------------------------------------
# 一对一字段的数据的修改和一对多一样的。
# 增
# 第一种方式:
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.create(title='红楼梦',price=444,publish=publish_obj)
# 第二种方式:
models.Book.objects.create(title='三国演义',price=222,publish_id=1) # 改
# 第一种方式:
models.Book.objects.filter(pk=2).update(publish_id=2)
# 第二种方式:
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(pk=2).update(publish=publish_obj) # 删 默认就是级联删除,级联更新
models.Publish.objects.filter(pk=1).delete()

多对多字段数据的操作

方法 描述
add 能够在第三张表中添加数据既支持传数字,也支持传对象,可以传多个值
set 修改第三张表中的数据,需要传一个可迭代对象进去例如元组,列表,容器类元素可以是数字或者对象
remove 删除第三张表中的数据,既支持传数字,也支持传对象,可以传多个值
clear 清空 删除书籍相关的记录,下线,括号内不需要传递参数
# 多对多字段数据的增删改查------------------------------------------------------------------------
# 增
book_obj = models.Book.objects.filter(pk=2).first()
# print(book_obj.authors)
# app01.Author.None 表示着已经跨到第三张表了
# 给当前这一本书绑定作者,可以写多个
book_obj.authors.add(1)
book_obj.authors.add(1,2) # 也可以增加对象
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj1,author_obj2) '''
add 方法:
能够在第三张表中添加数据
既支持传数字,也支持传对象,可以传多个值
''' # 改
# 修改id为2的书籍的作者
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.set((1,))
book_obj.authors.set((1,2)) # 也可以修改为对象
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.authors.set((author_obj1,author_obj2)) '''
set 方法:
修改第三张表中的数据,
需要传一个可迭代对象进去例如元组,列表,
容器类元素可以是数字或者对象
''' # 删
# 删除id为2的书籍的作者
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.author.remove(1,2) # 也可以传对象
author_obj1 = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
book_obj.author.remove(author_obj1, author_obj2) '''
remove 方法:
删除第三张表中的数据,既支持传数字,也支持传对象,可以传多个值
''' # 清空:
# 删除id为2 的书籍(包括作者信息也删除)
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.clear() '''
clear 方法:
清空 删除书籍相关的记录,下线,括号内不需要传递参数
'''

跨表查询

在使用跨表查询的时候,要注意一点,

要明白关系字段在哪一方?

从有关系字段的那一方查的话就是正向查询,查询按关系字段查询查。

从没有关系字段的那一方查的话就是反向查询,查询按小写的表名查。

基于对象的跨表查询

方法 描述
all() 当正向查询点击外键字段数据有多个的情况下也就是多对多查询,需要加.all()
_set 反向查询的时候 表名小写并且加_set

子查询

# 跨表查询------------------------------------------------------------------------
# 基于对象的跨表查询
# 1. 查询书籍主键为2的出版社名称
# 正向查询,先查书籍对象,一对多查询
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.publish.name) # 2. 查询书籍主键为2的作者姓名
# 正向查询,先查书籍对象,多对多查询
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.authors) # app01.Author.None
print(book_obj.authors.all().values('name')) # 3. 查询作者是qinyj的手机号码
# 正向查询,先查作者对象,一对一查询
author_obj = models.Author.objects.filter(name='qinyj').first()
print(author_obj.author_detail.phone) '''
什么时候需要加 all:
当正向查询点击外键字段数据有多个的情况下
也就是多对多查询,需要加.all()
''' # 4. 查询出版社是东方出版社出版过的书籍
# 反向查询,先查出版社对象,一对多查询
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set.all().values('title')) # 5. 查询作者是qinyj写过的书籍
# 反向查询,先查作者对象,多对多查询
author_obj = models.Author.objects.filter(name='qinyj').first()
print(author_obj.book_set.all().values('title')) # 6. 查询手机号是111111的作者姓名
# 反向查询,先查作者详情表的对象,一对一查询
author_detail_obj = models.AuthorDetail.objects.filter(phone='111111').first()
print(author_detail_obj.author.name) '''
什么时候反向查询的时候表名小写并且加_set
一对多
多对多
一对一不需要加
'''

基于双下划线的跨表查询

联表查询

双下划线,链式操作:__

# 基于双下划线的跨表查询 联表操作------------------------------------------------------------------------
# 1. 查询书籍id为2的出版社名称
# 正向查询:
# values中写外键名就相当于跨到外键字段所在的表中了
print(models.Book.objects.filter(pk=2).values('publish__name'))
# 反向查询:
print(models.Publish.objects.filter(book__pk=2).values('name')) # 2. 查询书籍id为2的作者的姓名
# 正向查询:
print(models.Book.objects.filter(pk=2).values('authors__name'))
# 反向查询:
print(models.Author.objects.filter(book__pk=2).values('name')) # 3. 查询作者是qinyj的地址
# 正向查询:
print(models.Author.objects.filter(name='qinyj').values('author_detail__add'))
# 反向查询:
print(models.AuthorDetail.objects.filter(author__name='qinyj').values('add')) # 4. 查询出版社是东方出版社出版过的书的名字
# 正向查询:
print(models.Book.objects.filter(publish__name='东方出版社').values('title'))
# 反向查询:
print(models.Publish.objects.filter(name='东方出版社').values('book__title')) # 5. 查询书籍id是2的作者的手机号
# 正向查询:
print(models.Book.objects.filter(pk=2).values('authors__author_detail__phone'))
# 反向查询:
print(models.Author.objects.filter(book__pk=2).values('author_detail__phone'))

聚合函数

aggregate

聚合函数 描述
Max 最大值
Min 最小值
Sum 求和
Count 计数
Avg 平均数
'''
聚合函数
'''
from django.db.models import Max,Min,Count,Avg,Sum # 筛选出价格最高的书籍
print(models.Book.objects.aggregate(ct=Count('price'))) # {'ct': 2} # 筛选出价格最低的书籍
print(models.Book.objects.aggregate(mn=Min('price'))) # {'mn': Decimal('222.00')} # 求书籍价格总和
print(models.Book.objects.aggregate(sm=Sum('price'))) # {'sm': Decimal('666.00')} # 求书籍价格平均值
print(models.Book.objects.aggregate(ag=Avg('price'))) # {'ag': 333.0} # 联用
print(models.Book.objects.aggregate(Max('price')),Min('price'),Sum('price'),Count('price'))

分组查询

annotate

'''
分组查询,通常和聚合函数一起使用
'''
# 1. 统计每一本书的 书名和对应的作者个数
print(models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')) # 2. 统计每各出版社卖的最便宜的书的价格
print(models.Publish.objects.annotate(book_num=Min('book__price')).values('name','book_num')) # 3. 按照指定的字段进行分组
print(models.Publish.objects.values('name').annotate(max_price=Max('book__price')).values('name','max_price')) # 4. 统计不止一个作者的图书
# 首先拿到书对应的作者数,再筛选出大于一的图书,作者个数
print(models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title','author_num')) # 5. 查询每个作者出的书的总价格
print(models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price'))

F与Q查询

'''
F 查询
'''
from django.db.models import F,Q # 1. 查询库存数大于卖出数的书籍
print(models.Book.objects.filter(kucun_num__gt=F('maichu_num')).values('title')) # 2. 将所有书的价格都上涨100块
models.Book.objects.all().update(price=F('price')+100) # 3. 将所有书的名字后面都加上 后缀名
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.update(title=Concat(F('title'),Value('新款'))) '''
Q 查询
'''
# 1. 查询书籍名是三国演义或者 库存数是500的书籍
print(models.Book.objects.filter(title='三国演义',kucun_num=500)) # 默认是and的关系
print(models.Book.objects.filter(Q(title='三国演义') | Q(kucun_num=500))) # 用了 | 就是or的关系
print(models.Book.objects.filter(~Q(title='三国演义') | Q(kucun_num=500))) # 用了 | 就是or的关系 '''
Q对象高级用法
'''
q = Q()
q.connector = 'or' # 默认是and,可以改成or
q.children.append(('title','三国演义'))
q.children.append(('kucun_num',500))
print(models.Book.objects.filter(q))

ORM事务

还记得在Mysql数据库中的事务操作吗?

在MySQL中只有使用Innodb数据库引擎的数据库或表才支持使用事务

事务必须满足4个条件(ACID):

  • 原子性:一个事务中的所有操作,要么全部执行,要么全部回滚,中间不会结束在任何一个环节。
  • 一致性:在事务开始和事务结束之后,数据不会出错
  • 隔离性:数据库允许多个并发事务同时对数据进行读写和修改,每个事务相互隔离
  • 持久性:事务处理结束后,对数据的修改是永久的
from django.db import transaction

with transaction.atomic():
# 在缩进的代码中书写数据库的操作
# 该缩进下的所有代码,都是一个事务
pass # 对整个view视图开启事务
@transaction.atomic
def index(request):
//ORM操作
return ....

例子

1.创建一个项目,新建一个APP(基础操作,这里不再赘述)

2.通过ORM创建生成表

from django.db import models

class UserInfo(models.Model):
username = models.CharField("用户",max_length=32)
balance = models.CharField("余额",max_length=32)

注意啊:踩过的坑,涉及金融计算,涉及小数啊,要求特别精确的,我们用字符串存储。

如果是金融计算的话,我们用一个decimal来进行计算。

3.我们给数据库加两条数据,用来模拟两个用户之间的转账

4.配置URL

5.创建对应的视图函数

from django.shortcuts import render,HttpResponse
from app01 import models
from django.db import transaction
from django.db.models import F def index(request):
try:
with transaction.atomic():
models.UserInfo.object.filter(id=1).update(balance=F("balance")-100)
models.UserInfo.object.filter(id=2).update(balance=F("balance")+100)
except Exception as e:
return HttpResponse("出现错误<%s>"%str(e))
return HttpResponse("执行成功")

当我们访问index的时候,会进行一次转账操作

6.现在,我们让他报错

from django.shortcuts import render,HttpResponse
from app01 import models
from django.db import transaction
from django.db.models import F def index(request):
try:
with transaction.atomic():
models.UserInfo.object.filter(id=1).update(balance=F("balance")-100)
raise 一个错误
models.UserInfo.object.filter(id=2).update(balance=F("balance")+100)
except Exception as e:
return HttpResponse("出现错误<%s>"%str(e))
return HttpResponse("执行成功")

我们再次查看数据库文件,如果没有数据的原子性操作,我们第一条sql执行完报错,那钱肯定是减去了

但是,我们进行的是原子性的操作,你会发现钱没有减诶。

完美,没毛病

数据库中的三大范式

范式(Normal Form),缩写NF,规范化形式,简称范式。

目的是增加数据有效性,减少数据冗余,提高存储效率

  • 1NF:数据库中的每一个字段,必须是不可拆分的最小单位。
  • 2NF:表中所有字段都必须有意义,一个表只描述某一个事物
  • 3NF:表中不能有其他表中存在的、存储相同信息的字段,通常是通过外键去建立关联,外键约束

第一范式(1NF)

数据库中的每一个字段,必须是不可拆分的最小单位。

即一个字段就表示一个意思,表中不能同时有2个字段来表示同一个意思

正例:

根据业务需求来合理使用行政区域

反例:

其中 address 可以再分为省、市、地区(县)、街道、详细地址,违反了第一范式。

第二范式(2NF)

表中所有字段都必须有意义,一个表只描述某一个事物

主键存在的意义就是唯一的标识表中的某一条记录,如果某一列和该行记录没关系,也就没必要存在。

反例:

此表中,天气(weather字段)和用户没啥关系,也就不存在依赖关系,所不符合 第二范式。正确的做法应)该删除此列,如有其他需要可单独存在一张表中。

第三范式(3NF)

表中不能有其他表中存在的、存储相同信息的字段,通常是通过外键去建立关联,外键约束

反例:

上面是一个订单表,字段从左至右以此是:订单id、买家id、买家名称、买家性别、买家年龄、订单状态。其中字段buyer_name、buyer_gender、buyer_age 是依赖于字段 buyer_info_id,违反 第二范式。

正例:

订单表

买家信息表

数据库五大约束

  • 主键约束(Primary Key):非空唯一,例如 将UserId作为主键
  • 唯一约束(Unique):唯一,可以空,但只能有一个,例如 身份证号唯一,因为每个人的都不一样
  • 检查约束(Check):对该列数据的范围、格式的限制(如:年龄、性别),例如 对年龄加以限定 20-40岁之间
  • 默认约束(Default):该数据的默认值,例如 如果地址不填 默认为“地址不详”
  • 外键约束(Foreign Key):需要建立两表间的关系,例如 建立外键

Django之深入了解ORM的更多相关文章

  1. python 全栈开发,Day70(模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介)

    昨日内容回顾 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 Quer ...

  2. {Django基础六之ORM中的锁和事务}一 锁 二 事务

    Django基础六之ORM中的锁和事务 本节目录 一 锁 二 事务 一 锁 行级锁 select_for_update(nowait=False, skip_locked=False) #注意必须用在 ...

  3. Django基础(2)--模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介

    没整理完 昨日回顾: 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 ...

  4. day 71 Django基础六之ORM中的锁和事务

    Django基础六之ORM中的锁和事务   本节目录 一 锁 二 事务 三 xxx 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 锁 行级锁 select_for_update(no ...

  5. Django模型层之ORM

    Django模型层之ORM操作 一 ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数据库管理软 ...

  6. day 58 Django基础六之ORM中的锁和事务

      Django基础六之ORM中的锁和事务   本节目录 一 锁 二 事务 三 xxx 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 锁 行级锁 select_for_update( ...

  7. Django框架之数据库ORM框架

    首先,我来介绍一下什么是ORM框架: O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思.在ORM框架中,它帮 ...

  8. 【Django】--Models 和ORM以及admin配置

    Models 数据库的配置 1    django默认支持sqlite,mysql, oracle,postgresql数据库 <1>sqlite django默认使用sqlite的数据库 ...

  9. Django 源码小剖: Django 对象关系映射(ORM)

    引 从前面已经知道, 一个 request 的到来和一个对应 response 的返回的流程, 数据处理和数据库离不开. 我们也经常在 views.py 的函数定义中与数据库打交道. django O ...

  10. Django(四) ORM 外键操作及初识Ajax

    一.内容回顾 1.Django请求的生命周期: ​ 路由系统 -> 视图函数(获取模板+数据 -> 渲染) -> 字符串返回给用户 2.路由系统: /index/ #-> 函数 ...

随机推荐

  1. 第一章:Lambda表达式入门概念

    要点:将行为像数据一样传递. 一.几种形式 1.没有参数,用()表示 () ->System.out.println("Hello World"); 2.有且仅有一个参数,省 ...

  2. 使用SDK方式进行微信授权

    1.在pom.xml中添加依赖 <dependency> <groupId>com.github.binarywang</groupId> <artifact ...

  3. SparkStreaming整合Flume的pull方式之启动报错解决方案

    Flume配置文件: simple-agent.sources = netcat-source simple-agent.sinks = spark-sink simple-agent.channel ...

  4. Restoring Road Network Floyd

    问题 C: Restoring Road Network 时间限制: 1 Sec  内存限制: 128 MB提交: 731  解决: 149[提交] [状态] [讨论版] [命题人:admin] 题目 ...

  5. MD5/SHA1/Hmac_SHA1

    1.MD5 #import <CommonCrypto/CommonDigest.h> + (NSString *) md5:(NSString *) input { const char ...

  6. nodejs入门安装与调试,mac环境

    install nvm (node version manager) 安装nvm curl -o- https://raw.githubusercontent.com/creationix/nvm/v ...

  7. 深度探索C++对象模型之第一章:关于对象之C++对象模型

    一.C和C++对比: C语言的Point3d: 数据成员定义在结构体之内,存在一组各个以功能为导向的函数中,共同处理外部的数据. typedef struct point3d { float x; f ...

  8. BlueHost主机建站方案怎样选择?

    BlueHost是知名美国主机商,近年来BlueHost不断加强中国市场客户的用户体验,提供多种主机租用方案,基本能够满足各类网站建设需求.下面就和大家介绍一下建站应该怎样选择主机. 1.中小型网站 ...

  9. CSIC_716_20191118【常用模块的用法 Json、pickle、collections、openpyxl】

    序列化模块 序列化:将python或其他语言中的数据类型,转变成字符串类型. python中的八大数据类型回顾:int float str list tuple dict set bool 反序列化: ...

  10. css----less预处理器

    ###less less是一种动态样式语言,属于css预处理器的范畴,它扩展了 CSS 语言, 增加了变量.Mixin.函数等特性,使 CSS 更易维护和扩展 LESS 既可以在 客户端 上运行 ,也 ...