week11 day7 模型层

  • 模型层
    • 一、django测试环境的搭建
    • 二、单表查询关键字(精准查找)
      • 必知必会13条
    • 三、神奇的双下划线查询(范围查询)
    • 四、图书管理系统的表设计
    • 五、外键字段的增删改查
      • 5.1 一对多绑定外键增删改
      • 5.2 多对多绑定外键增删改查
    • 六、基于对象的跨表查询(子查询)
    • 七、基于下划线的跨表查询(链表查询)
    • 八、聚合查询aggregate
    • 九、分组查询annotate
    • 十、F和Q查询
    • 十一、django中开启事务
    • 十二、ORM中常用字段及参数
    • 十三、字段关系 / 手动创建第三张表 / 元信息 / 原生SQL
      • 13.1 字段关系
      • 13.2 手动创建第三张表的三种方式
      • 13.3 元信息
      • 13.4 原生SQL
    • 补充:

模型层

一、django测试环境的搭建

  1. pycharm链接数据库都需要自己先下载驱动的。
  2. 自带的sqlite3对日期格式不敏感。如果后续业务需要使用日期辅助筛选数据,那么不推荐使用自带数据库,而使用MySQL。

django默认是一个整体,不会让你单独操作其中的某一个模块。所以需要配置或者利用django自带的python console。

"""
当你只是想测试django中的某一个py文件内容,那么你可以不同书写前后端交互的形式而是直接写一个测试脚本即可
"""

测试环境的准备:

第一种方法:把manage.py里面的前四行代码拷贝过来,后面加上import djangodjango.setup()

import osif __name__ == "__main__":os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoDBCURD.settings")# 配置django项目的环境变量(os模块是配置系统变量的模块),将暴露给用户的配置信息加载好import djangodjango.setup()  # 使用环境变量中的配置文件,跑django项目from app01 import modelsres = models.Userinfo.objects.all()

第二种方法:利用django自带的python console

二、单表查询关键字(精准查找)

# 方式一:queryset对象.query查看内部query语句
v1 = models.User.objects.values_list('name')  # <QuerySet [('jason',), ('wc',)]>可以理解成列表套元组
print(v1)
print(v1.query)  # SELECT `app01_user`.`name` FROM `app01_user`# 方式二:添加配置信息
LOGGING = {'version': 1,'disable_existing_loggers': False,'handlers': {'console':{'level':'DEBUG','class':'logging.StreamHandler',},},'loggers': {'django.db.backends': {'handlers': ['console'],'propagate': True,'level':'DEBUG',},}
}

必知必会13条

# 增# 方法一:利用create自动保存res = models.User.objects.create(name='jason', age=20, register_time='2002-1-21')print(res)import datetimectime = datetime.datetime.today()# 方法二:手动创建数据对象,手动保存user_obj = models.User(name='evan', age=30, register_time=ctime)user_obj.save()print(user_obj)# 删# 方法一:批量删除res = models.User.objects.filter(pk=2).delete()print(res)  # (1, {'app01.User': 1})"""pk会自动查找到当前表的主键字段,指代的是当前表的主键字段用了pk之后,你就不需要知道按当前表的主键字段到底叫什么了"""# 方法二:获取到数据对象,针对性删除user_obj = models.User.objects.filter(pk=1).first()user_obj.delete()print(user_obj)# 改user_obj = models.User.objects.filter(pk=4).update(name='wc')print(user_obj)user_obj = models.User.objects.get(pk=7)  # 不推荐"""get方法返回地直接就是当前数据对象,但是该方法不推荐使用,一旦数据不存在该方法会直接报错app01.models.DoesNotExist: User matching query does not exist.而filter不会直接报错"""# 必知必会13条# 1.all() 查询所有数据【QuerySet对象】# 2.filter() 带有过滤条件的查询【QuerySet对象】# 3.get() 直接拿数据对象,但是条件不存在直接报错【数据对象or报错】# 4.first() 拿queryset里面的第一个元素【数据对象】res = models.User.objects.all().first()print(res.name)# 5.last() 拿queryset里面的最后一个元素【数据对象】res1 = models.User.objects.all().last()print(res1.register_time)# 6.values() 可以指定获取的数据字段,该方法的返回结果是列表套字典【QuerySet对象】v = models.User.objects.values('name')print(v)  # <QuerySet [{'name': 'jason'}, {'name': 'wc'}]>可以理解成列表套字典# 7.values_list() 列表套元组【QuerySet对象】v1 = models.User.objects.values_list('name') # <QuerySet [('jason',), ('wc',)]>可以理解成列表套元组print(v1)print(v1.query)  # SELECT `app01_user`.`name` FROM `app01_user`"""上述查看SQL语句的方式,只能用于queryset对象"""# 8.distinct()【QuerySet对象】res = models.User.objects.values('name', 'age').distinct()print(res)  # 可以理解成列表套元组"""去重一定要是一模一样的数据如果带有主键那么肯定不一样,在往后的查询中一定不要忽略主键!!!"""# 9.order_by()【QuerySet对象】res = models.User.objects.values('name').order_by('-name')print(res)# 默认升序。前面加一个 - 就变成了降序# 10.reverse() 反转的前提是数据已经排序过了【QuerySet对象】res = models.User.objects.all()res1 = models.User.objects.values('name', 'age').order_by('age').reverse()print(res1)# 11.count() 统计当前数据的个数res = models.User.objects.count()print(res)# 12.exclude()【QuerySet对象】res = models.User.objects.exclude(name='wc')print(res)# 13.exists() 基本用不到,返回的是布尔值【boolean值】res = models.User.objects.filter(pk=4).exists()print(res)
获得QuerySet 获得数据对象 获得数字 获得布尔值
方法 all、filter、values、values_list、distinct、order_by、reverse、exclude first、get、last count exists

三、神奇的双下划线查询(范围查询)

"""
DateField
DateTimeField两个重要参数:auto_now:每次操作数据的时候,该字段会自动将当前时间更新auto_now_add:在创建数据的时候会自动将当前操作时间记录下来,之后只要不人为修改,那么会一直不变
"""# 神奇的双下划线查询1.年龄大于35岁的数据res = models.User.objects.filter(age__gt=20)print(res)2.年龄小于20岁的数据res = models.User.objects.filter(age__lt=20)print(res)3.大于等于、小于等于res = models.User.objects.filter(age__gte=30)res1 = models.User.objects.filter(age__lte=30)print(res, res1)4.年龄是18/32/40res = models.User.objects.filter(age__in=[20, 32, 40])print(res)5.年龄在30到40岁之间的  顾头也顾尾res = models.User.objects.filter(age__range=[30, 40])print(res)6.查询出名字里面含有n的数据。默认是区分大小写的,如果想要忽略大小前面加ires = models.User.objects.filter(name__contains='n')res1 = models.User.objects.filter(name__icontains='n')print(res, res1)7.名字以xxx开头的/xxx结尾的res0 = models.User.objects.filter(name__startswith='mmm')res = models.User.objects.filter(name__endswith='mmm')8.查询出注册时间。按年year,按月month,按日dayres = models.User.objects.filter(register_time__day=20)res1 = (models.User.objects.filter(register_time__year=1970))print(res, res1)

四、图书管理系统的表设计

class Book(models.Model):title = models.CharField(max_length=32)price = models.DecimalField(max_digits=8, decimal_places=2)publish_data = models.DateField(auto_now_add=True)# 一对多publish = models.ForeignKey(to='Publish')# 多对多authors = models.ManyToManyField(to='Author')# 在django 2.x 版本中,不再默认级联更新和级联删除。需要自己指定authors = models.ManyToManyField(to='Author', on_delete=SET_DEFAULT(需要在后面加上default=xxx)/SET/DO_NOTHING/SET_NULL)class Publish(models.Model):name = models.CharField(max_length=32)addr = models.CharField(max_length=128)email = models.EmailField()  # varchar(254) 该字段类型 不是给models看的,而是给后面校验型组件看的class Author(models.Model):name = models.CharField(max_length=32)age = models.IntegerField()# 一对一author_detail = models.OneToOneField(to='AuthorDetail')class AuthorDetail(models.Model):phone = models.CharField(max_length=12)addr = models.CharField(max_length=256)

五、外键字段的增删改查

5.1 一对多绑定外键增删改

# 一对多外键增删改查# 增# 1.直接写实际字段 idmodels.Book.objects.create(title='三国演义', price=123.23, publish_id=1)# 2.虚拟字段  对象pub_obj = models.Publish.objects.filter(pk=2).first()models.Book.objects.create(title='红楼梦', price=666.23, publish=pub_obj)# 删models.Publish.objects.filter(pk=1).delete()# 修改# 1.直接写实际字段 idmodels.Book.objects.filter(pk=3).update(publish_id=2)# 2.虚拟字段 对象publish_obj = models.Publish.objects.filter(pk=1).first()models.Book.objects.filter(pk=3).update(publish=publish_obj)

5.2 多对多绑定外键增删改查

# 多对多表关系的增删改查,就是在操作第三张表# 如何给书籍绑定作者?(增:在原来基础上增加)book_obj = models.Book.objects.filter(pk=3).first()# print(book_obj.authors)  # 就类似于你已经到了第三张关系表了 app01.Author.None# book_obj.authors.add(1)  # 书籍id为 1 的书籍绑定一个主键为 1 的作者# book_obj.authors.add(2, 3)author_obj = models.Author.objects.filter(pk=1).first()author_obj1 = models.Author.objects.filter(pk=2).first()author_obj2 = models.Author.objects.filter(pk=3).first()book_obj.authors.add(author_obj, author_obj1, author_obj2)"""add给第三张表添加数据括号内既可以传数字也可以传对象,并且都支持多个,以逗号隔开即可"""# 删book_obj.authors.remove(2)book_obj.authors.remove(1, 3)book_obj.authors.remove(author_obj, author_obj2)# 改:先清空再设置book_obj = models.Book.objects.filter(pk=4).first()# book_obj.authors.set(1)  # TypeError: 'int' object is not iterable# book_obj.authors.set([1, 2])author_obj = models.Author.objects.filter(pk=3).first()author_obj1 = models.Author.objects.filter(pk=1).first()book_obj.authors.set([author_obj, author_obj1])"""set括号内必须传一个可迭代对象,该对象内既可以数字也可以对象,并且都支持多个"""# 清空# 在第三张关系表中清空某个书籍与作者的绑定关系book_obj.authors.clear()"""括号内不要放任何值"""

六、基于对象的跨表查询(子查询)

正反向概念:

  1. 外键字段在我手上,我查你就是正向
  2. 外键字段如果不在我手上,我查你就是反向

book >>> 外键字段在书那(正向) >>> publish

publish >>> 外键字段在书那(反向) >>> book

  1. 先查询出一个对象

  2. 基于对象点正反向字段
    正向点外键字段

    ​ 反向点表名小写

# 基于对象的跨表查询# 1.查询书籍主键为 3 的出版社名称book_obj = models.Book.objects.filter(pk=3).first()# 书查出版社,外键在书,正向-----》点主键字段res = book_obj.publishprint(res.name)# 2.查询书籍主键为3的作者book_obj = models.Book.objects.filter(pk=3).first()# 书查作者,外键在书,正向-----》点主键字段# res = book_obj.authors  # app01.Author.Noneres = book_obj.authors.all()  # <QuerySet [<Author: Author object>, <Author: Author object>, <Author: Author object>]>print(res)# 3.查询作者jason的电话号码author_obj = models.Author.objects.filter(name='jason').first()res = author_obj.author_detailprint(res.phone)"""在书写orm语句的时候和书写SQL语句一样的,不要企图一次性把orm语句写完,如果比较复杂,就写一点看一点正向什么时候需要加.all()当你的结果可能有多个的时候就需要加.all()如果是一个则直接拿到数据对象"""# 4.查询出版社是东方出版社出版的书publish_obj = models.Publish.objects.filter(name='东方出版社').first()# res = publish_obj.book_set  # app01.Book.Noneres = publish_obj.book_set.all()print(res.values('title'))# 5.查询作者是jason写过的书author_obj = models.Author.objects.filter(name='jason').first()# res = author_obj.book_setres = author_obj.book_set.all()print(res)    # 6.查询手机号110的作者姓名author_obj = models.AuthorDetail.objects.filter(phone=110).first()res = author_obj.authorprint(res)"""当你的查询结果有多个时候,就必须加_set.all()当你的结果只有一个的时候,不需要加_set.all()"""

七、基于下划线的跨表查询(链表查询)

# 1.查询jason的手机号res = models.Author.objects.filter(name='jason').values('author_detail__phone')print(res)# 反向# res = models.AuthorDetail.objects.filter(author__name='jason') # 拿作者姓名是jason的外键字段res = models.AuthorDetail.objects.filter(author__name='jason').values('phone')print(res)# 2.查询书籍主键为3的出版社名称和书的名称res = models.Book.objects.filter(pk=3).values('publish__name', 'title')print(res)# 反向res = models.Publish.objects.filter(book__pk=3).values('name', 'book__title')print(res)# 3.查询书籍主键为3的作者姓名res = models.Book.objects.filter(pk=3).values('authors__name')print(res)# 反向res = models.Author.objects.filter(book__pk=3).values('name')print(res)# 4.查询书籍主键是3的作者的手机号res = models.Author.objects.filter(book__pk=3).values('author_detail__phone')print(res)"""你只要掌握了正反向的概念以及双下划线就可以无限制的跨表"""

八、聚合查询aggregate

# 聚合查询  aggregate"""聚合查询通常情况下都是配合分组一起使用的只要跟数据库相关的模块:基本上都在django.db.models里面如果上述没有那么应该在django.db里面"""from django.db.models import Max, Min, Sum, Count, Avg# 1.所有书的平均价格res = models.Book.objects.aggregate(Avg('price'))print(res)  # {'price__avg': 493.316}# 加点要求:egon出版书的平均价格res = models.Book.objects.filter(author__name='egon').aggregate(Avg('price'))    # 2.上述方法一次性使用res = models.Book.objects.aggregate(Max('price'), Min('price'), Sum('price'), Count('pk'))print(res)  # {'price__max': Decimal('899.23'), 'price__min': Decimal('123.23'), 'price__sum': Decimal('2466.58'), 'pk__count': 5}from django.db.models import F, Q# 把egon出版的所有图书价格加10res = models.Book.objects.filter(authors__name='egon')print(res.values('price'))res.update(price=F('price')+10)print(res.values('price'))# 查询名字叫红楼梦或价格大于800的书res = models.Book.objects.filter(Q(title='红楼梦') | Q(price__gt=800))print(res.values('title'))# 查询名字叫红楼梦和价格大于100  或者 pk大于6res = models.Book.objects.filter(Q(title='红楼梦', price__gt=900) | Q(pk__gt=6))print(res.values('title'))# 查询名字不是红楼梦,并且价格大于100的书res = models.Book.objects.filter(~Q(title='红楼梦'), price__gt=900)print(res.values('title'))# 把聚合查询的结果重命名

九、分组查询annotate

# !!!分组查询使用方法!!!
"""标准 annotate() 内写聚合函数values在前,表示group_by的字段values在后,表示取字段filter在前,表示where条件filter在后,表示having条件(一时间想不到怎么写就用原生SQL语句书写,再通过逐步转换成ORM语法的写法)
同时,强烈建议使用分组的表作为基表。
"""
# 分组查询 annotate"""MySQL分组查询都有哪些特点?分组之后默认只能获取到分组的依据,组内其他字段都无法直接获取了严格模式ONLY_FULL_GROUP_BY"""# 1.统计每一本书的作者个数res = models.Book.objects.annotate()  # models后面点什么 就是按照什么分组res1 = models.Book.objects.annotate(author_num=Count('authors')).values('title', 'author_num')"""author_num是我们自定义的字段,用来存储统计出来的每本书对应的作者个数"""print(res, res1)# <QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>, <Book: Book object>,#   <Book: Book object>]> <QuerySet [{'title': '三国演义', 'author_num': 3}, {'title': '红楼梦', 'author_num': 0},#   {'title': '论语', 'author_num': 0}, {'title': '聊斋', 'author_num': 0}, {'title': '老子', 'author_num': 0}]>"""代码没有补全,不要怕,正常写补全是pycharm提供的功能,到后面在服务器上直接书写代码,什么补全都没有"""# 2.统计每个出版社卖的最便宜的书得价格res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name', 'min_price')print(res)  # <QuerySet [{'name': '东方出版社', 'min_price': Decimal('123.23')}, {'name': '西方出版社', 'min_price': Decimal('444.23')}]># 3.统计不止一个作者的图书# 1.先按照图书分组,求每一本书的作者个数# 2.过滤出不止一个作者的图书res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)"""只要你的ORM语句得到的还是一个queryset对象那么他就可以继续无限制的点queryset对象封装的方法"""print(res.first().title)  # 三国演义# 4.查询每个作者出版的书的总价格res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name', 'sum_price')print(res)# <QuerySet [{'name': 'egon', 'sum_price': Decimal('123.23')}, {'name': 'jason', 'sum_price': Decimal('123.23')},#   {'name': 'tank', 'sum_price': Decimal('123.23')}]>from django.db.models import Max, Min, Count, Sum, Avg# 查询出版社id大于1的出版社id,以及出书平均价格# select id, Avg(book__price) from publish where id>1 group by idres = models.Publish.objects.filter(pk__gt=1).values('pk').annotate(avgprice=Avg('book__price')).values('id', 'avgprice')print(res)# 查询出版社id大于1的出版社id,以及出书平均价格大于500的res = models.Publish.objects.filter(pk__gt=1).values('pk').annotate(avg_price=Avg('book__price')).\filter(avg_price__gt=500).values('pk', 'avg_price')print(res)## 查询每一个出版社出版的书籍个数res = models.Publish.objects.values('pk').annotate(count_num=Count('book')).values('pk', 'count_num')print(res)# 如果没有指定group by的字段,默认就用基表(Publish)主键字段作为group by的字段ret=models.Publish.objects.annotate(count=Count('book__id')).values('name','count')print(ret)# 另一种方式实现ret=models.Book.objects.values('publish').annotate(count=Count('id')).\values('publish__name','count')print(ret)#查询每个作者的名字,以及出版过书籍的最高价格(建议使用分组的表作为基表)# 如果不用分组的表作为基表,数据不完整可能会出现问题res = models.Author.objects.values('pk').annotate(max_price=Max('book__price')).values('name', 'max_price')print(res)# 如果有没有绑定作者的书,这里就会出现一个None,表示无作者出版的书里面最贵的书res = models.Book.objects.values('authors__pk').annotate(max_price=Max('price')).values('authors__name', 'max_price')print(res)#查询每一个书籍的名称,以及对应的作者个数res = models.Book.objects.values('title').annotate(count_authors=Count('authors')).values('title', 'count_authors')print(res)#统计不止一个作者的图书res = models.Book.objects.values('title').annotate(count_authors=Count('authors')).filter(count_authors__gt=1).values('title', 'count_authors')print(res)# 统计价格数大于10元,作者的图书res = models.Author.objects.filter(book__price__gt=1000).values('name', 'book__title')print(res)#统计价格数大于10元,作者个数大于1的图书res = models.Author.objects.filter(book__price__gt=800).values('book__title').\annotate(count_authors=Count('name')).filter(count_authors__gt=1)print(res)"""如果我想按照指定的字段分组该如何处理呢?models.Book.objects.values('price').annotate()后续的BBS作业会使用如果机器上出现了分组查询报错的情况去数据库设置严格模式"""

十、F和Q查询

#  F 与 Q 查询# 1.查询出卖出数大于库存数的书籍# f查询"""能够帮助直接获取表中某个字段对应的数据"""from django.db.models import Fres = models.Book.objects.filter(maichu__gt=F('kucun'))print(res.first().title)# 2.将所有书籍的价格提升50块models.Book.objects.update(price=F('price')+500)# 细化要求,egon出版的书价格提供50块models.Book.objects.filter(author__name='egon').update(price=F('price')+50)# 3.将所有书的名称后面加上爆款两个字"""在操作字符类型的数据的时候,F不能直接左到字符串的拼接"""from django.db.models.functions import Concatfrom django.db.models import Valuemodels.Book.objects.update(title=Concat(F('title'), Value('爆款')))# models.Book.objects.update(title=F('title'), '爆款')  所有的名称都会变成空白# Q 查询# 1.查询卖出数大于100或者价格小于600的书籍res = models.Book.objects.filter(maichu__gt=100, price__lt=600)"""filter括号内多个参数是and关系"""from django.db.models import Qres = models.Book.objects.filter(Q(maichu__gt=100), Q(price__lt=600))  # Q包裹逗号分隔,还是and关系# sql语句 WHERE (`app01_book`.`maichu` > 100 AND `app01_book`.`price` < 600)res1 = models.Book.objects.filter(Q(maichu__gt=100)|Q(price__lt=600))  # Q包裹 | 分割,是or关系# sql语句 WHERE (`app01_book`.`maichu` > 100 OR `app01_book`.`price` < 600)res2 = models.Book.objects.filter(~Q(maichu__gt=100) | Q(price__lt=600))  # Q包裹 ~ 分割,是not关系# sql语句 WHERE (NOT (`app01_book`.`maichu` > 100) OR `app01_book`.`price` < 600)print(res, res1, res2)# Q 的高阶用法    能够将查询条件的左边也变成字符串的形式q = Q()q.connector = 'or'q.children.append(('maichu__gt', 100))q.children.append(('price__lt', 600))res = models.Book.objects.filter(q)  # 默认还是and关系print(res.values('title'))

十一、django中开启事务

# 事务from django.db import transactionwith transaction.atomic():# sql1        # sql2# 在with代码块内书写的所有的orm操作都是属于同一个事务print('正在执行其他操作')

十二、ORM中常用字段及参数

1.AutoField主键字段 primary_key=True
2.CharField varcharverbose_name 字段的注释max_length     长度3.InterField  int
4.BigIntergerField  bigint
5.DecimalFieldmax_length=8decimal_places=26.EmailField    varchar(254)7.DateField date
8.DateTimeField  datetimeauto_now   每次修改数据的时候都会自动更新当前时间auto_now_add 只在创建数据的时候记录创建时间后续不会自动修改了9.BooleanField(Field)       布尔类型该字段传布尔值(False/True),数据库里面存0或110.TextField  文本类型该字段可以用来存大段内容(文章、博客...),没有字数限制后面的bbs作业,文章字段用的就是TextField11.FileField(Field)upload_to = "/data" 给该字段传一个文件对象,会自动保存到/data目录下然后将文件路径保存到数据库中/data/a.txt # django除了给你提供了很多字段类型之外,还支持你自定义字段
null                数据库中字段是否可以为空
db_column           数据库中字段的列名
db_tablespace
default             数据库中字段的默认值
primary_key         数据库中字段是否为主键
db_index            数据库中字段是否建立索引
unique              数据库中字段是否建立唯一索引
unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引(了解)
unique_for_month    数据库中字段【月】部分是否可以建立唯一索引(了解)
unique_for_year     数据库中字段【年】部分是否可以建立唯一索引(了解)
auto_now()          每次更新数据都会更新该字段【只对.save()方法有效,update无效】
auto_now_add()      只有在创建记录的时候记录时间,后续操作不更改时时间verbose_name        Admin中显示的字段名称
blank               Admin中是否允许用户输入为空
editable            Admin中是否可以编辑
help_text           Admin中该字段的提示信息
choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
get_gf_display

十三、字段关系 / 手动创建第三张表 / 元信息 / 原生SQL

13.1 字段关系

# 1.ForeignKey:外键字段在ORM中表示外键关联关系,一般把ForeignKey字段设置在 “一对多” 中 “多” 的一方# ForeignKey可以和其他表做关联关系同时也可以和自身做好关联关系
"""
to:设置要关联的表
to_field:设置要关联的的表的字段
related_name:反向操作时,使用的字段名,用于代替原反向查询时的’表名_set’。(了解即可)
related_query_name:反向查询操作时,使用的连接前缀,用于替换表名。(了解即可)on_delete:当删除关联表中的数据时,当前表与其关联的行的行为models.CASCADE: 删除关联数据,与之关联也删除models.DO_NOTHING: 删除关联数据,引发错误integrity errormodels.PROTECT: 删除关联数据,引发错误protected errormodels.SET_NULL: 删除关联数据,与之关联的值设置为默认值null(前提FK字段需要设置可为空)models.SET_DEFAULT: 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)models.SET:删除关联数据,a.与之关联的值设置为指定值,设置:models.SET(值)b.与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)(下例)db_constraint: 是否在数据库中创建外键约束,默认为True
"""
def func():return 10class MyModel(models.Model):user = models.ForeignKey(to="User",to_field="id",on_delete=models.SET(func))
# 2.OneToOneField:一对一字段。一对一关联的关系多用在当一张表的不同字段查询频次差距过大的情况下,将本可以存储在一张表的字段拆开放置在两张表中,然后将两张表建立一对一的关联关系。
class Author(models.Model):name = models.CharField(max_length=32)info = models.OneToOneField(to='AuthorInfo')class AuthorInfo(models.Model):phone = models.CharField(max_length=11)email = models.EmailField()"""
to:设置要关联的表
to_field:设置要关联的的表的字段
on_delete: 同foreignkey字段
"""
# 3.ManyToManyField: 用于表示多对多的关联关系。在数据库中通过第三张表来建立外键联系
"""
to: 设置要关联的表
related_name: 同ForeignKey字段。
related_query_name: 同ForeignKey字段。
symmetrical: 仅用于多对多自关联时,指定内部是否创建反向操作的字段。默认为True。(下例)
through: 在使用ManyToManyField字段时,Django将自动生成一张表来管理多对多的关联关系。但我们也可以手动创建第三    张表来管理多对多关系,此时就需要通过through来指定第三张表的表名。
through_fields: 设置关联的字段。
db_table: 默认创建第三张表时,数据库中表的名称。
"""
class Person(models.Model):name = models.CharField(max_length=16)friends = models.ManyToManyField("self")
# 此时,person对象就没有person_set属性
class Person(models.Model):name = models.CharField(max_length=16)friends = models.ManyToManyField("self", symmetrical=False)
# 此时,person对象现在就可以使用peorson_set的属性来进行反向查询

13.2 手动创建第三张表的三种方式

# 第一种:在建立表的时候添加多对多的字段,让数据库自动创建【最常见】# 优点:方便# 缺点:创建的字段少,有时可能无法满足我们的需求
class Book(models.Model):title = models.CharField(max_length=32, verbose_name="书名")# 通过ORM自带的ManyToManyField自动创建第三张表
class Author(models.Model):name = models.CharField(max_length=32, verbose_name="作者姓名")books = models.ManyToManyField(to="Book", related_name="authors")
# 第二种:自行创建第三张表【不太使用】# 优点:可以手动添加可能需要的字段# 缺点:操作麻烦,需要互相建立一对多关系两次。从书去作者需要Book__author2book__author
class Book(models.Model):title = models.CharField(max_length=32, verbose_name="书名")class Author(models.Model):name = models.CharField(max_length=32, verbose_name="作者姓名")# 自己完全手动创建第三张表,分别通过外键关联书和作者
class Author2Book(models.Model):author = models.ForeignKey(to='Book')book = models.ForeignKey(to='Author')# 还可以创建其他字段
# 第三种:设置ManyToManyField并指定自行创建的第三张表【使用频率仅次于自动创建第三张表】# 优点:利用了内置方法创建表还可以添加自己需要的字段。无论是基于对象的跨表查还是基于双下划线的跨表查都能继续使用# 缺点:原来的多对多操作api是用不了了。add、set、clear、delete。多表操作需要手动添加
class Book(models.Model):title = models.CharField(max_length=32, verbose_name="书名")# 自己创建第三张表,并通过ManyToManyField指定关联
class Author(models.Model):name = models.CharField(max_length=32, verbose_name="作者姓名")books = models.ManyToManyFiled(to=Book, through='author2book', through_fields=("author","book"))# through_fields接受一个二元组("field1","field2") # 其中field1是ManyToManyField所在表去中间表所需要走过的字段
"""
through: 在使用ManyToManyField字段时,Django将自动生成一张表来管理多对多的关联关系。但我们也可以手动创建第三    张表来管理多对多关系,此时就需要通过through来指定第三张表的表名。
through_fields: 设置关联的字段。
"""
class author2book(models.Model):author = models.ForeignKey(to=Author)book = models.ForeignKey(to=Book)

13.3 元信息

ORM对应的类里面包含一个meta类,而meta类封装了一些数据库的信息。主要字段如下:

# db_table: ORM在数据库中的表名默认是app_类名,可以通过db_table重命名。
# index_together: 联合索引。
# unique_together: 联合唯一索引。
# ordering: 指定默认按什么字段排序。只有设置了该字段,查询到的结果才可以reverse()操作。class UserInfo(models.Model):nid = models.AutoField(primary_key=True)username = models.CharField(max_length=32)class Meta:# 数据库中生成的表名称 默认 app名称 + 下划线 + 类名db_table = "table_name"# 联合索引index_together = [("pub_date", "deadline"),]# 联合唯一索引unique_together = (("driver", "restaurant"),)ordering = ('name',)# admin中显示的表名称verbose_name='哈哈'# verbose_name加sverbose_name_plural=verbose_name

13.4 原生SQL

from django.db import connection, connectionscursor = connection.cursor() # connection=default数据
cursor = connections['db2'].cursor()cursor.execute("""SELECT * from auth_user where id = %s""", [1])row = cursor.fetchone()
row = cursor.fetchall()
ret = models.Author.objects.raw('select * from app01_author where nid>1')
print(ret)
for i in ret:print(i)
print(ret.query)
# 会把book的字段放到author对象中
ret = models.Author.objects.raw('select * from app01_book where nid>1')
print(ret)
for i in ret:print(i.price)print(type(i))

补充:

  1. 普通函数以__开头

    说明当前函数只在当前模块(py)下使用,尽量不在外部调用

  2. MySQL的 utf8 不同于传统的 UTF-8。
    utf-8:1-4个字节,表示一个字符
    utf8:2个字节表示一个字符
    utf8-md4等同于真正意义上的utf-8

  3. 在django框架顶级(顶格书写)代码在启动django项目的时候都会优先执行

  4. django admin的功能

    1. 后台管理,方便快速的录入书籍2. 使用方法:# 第一步:在admin.py中把要使用的表注册from app01 import modelsadmin.site.register(models.Book)admin.site.register(models.Author)admin.site.register(models.AuthorDetail)admin.site.register(models.Publish)# 第二步:创建超级管理员python3 manage.py createsuperuser输入用户名root,输入密码12345wth# 输入密码过程中密码不显示(密码的要求:This password is too short. It must contain at least 8 characters.
    This password is entirely numeric.
    )# 第三步:登录,录入书籍http://127.0.0.1:8000/admin/
    
  1. api:开发者所提供的功能(接口)

    dtl(django template language):django模板语法。在模板中写python代码。

    php:url中index.php。.php 结尾的文件,先经过PHP 解析器翻译为html 标记文本,再被浏览器解析成网页。例:https://www.876p.cn/tags.php/https://www.baidu.com/index.*php*

    java(jsp):url中index.jsp。JSP技术以Java语言作为脚本语言,为用户的HTTP请求提供服务,并能与服务器上的其它Java程序共同处理复杂的业务需求。例:
    【具体内容看01 web框架 的补充部分】

  2. 什么时候创建第三张表?
    当第三张表需要额外字段的时候。

week11 day7 模型层相关推荐

  1. 【Django】模型层说明

    [Django模型层] 之前大概介绍Django的文章居然写了两篇..这篇是重点关注了Django的模型层来进行学习. ■ 模型定义 众所周知,Django中的模型定义就是定义一个类,其基本结构是这样 ...

  2. 阿里云物模型层功能分析

    文章目录 1 阿里云物模型层功能分析 1.1 AT软件框架图 1.2 设备和云端交换的数据类型 1.3 阿里云物模型层总体提供的能力 1 阿里云物模型层功能分析 1.1 AT软件框架图 首先还是来看一 ...

  3. Django之模型层和ORM

    在之前的文章中已经介绍过数据库的操作使用,但是不够系统,今天就模型层和ORM做一个系统的介绍.所谓模型层就是主要负责和数据库之间进行数据交互的一个模块 Django连接mysql数据库,安装mysql ...

  4. Web开发-Django模型层

    Django模型层 简述 Django框架处理业务的逻辑一般如下(省略图,源于网络,侵删) 可以看到,Django自带了一套ORM机制,这也是Django框架的核心-"全面",将一 ...

  5. Pytorch模型层简单介绍

    模型层layers 深度学习模型一般由各种模型层组合而成. torch.nn中内置了非常丰富的各种模型层.它们都属于nn.Module的子类,具备参数管理功能. 例如: nn.Linear, nn.F ...

  6. DJango周总结二:模型层,单表,多表操作,连表操作,数据库操作,事务

    django周复习二  1,模型层:   1单表操作:    13个必会操作总结     返回QuerySet对象的方法有     all()     filter()     exclude()   ...

  7. Django模板自定义标签和过滤器,模板继承(extend),Django的模型层

    上回精彩回顾 视图函数:request对象request.path 请求路径request.GET GET请求数据 QueryDict {}request.POST POST请求数据 QueryDic ...

  8. 速成pytorch学习——7天模型层layers

    深度学习模型一般由各种模型层组合而成. torch.nn中内置了非常丰富的各种模型层.它们都属于nn.Module的子类,具备参数管理功能. 例如: nn.Linear, nn.Flatten, nn ...

  9. 第六章节 三层架构(二. 模型层与数据访问层)

    一.模型层 1.由于三层之间存在数据交互,所以需要中间介质那就是"模型层",模型层包括与数据库表相对应的实体类,"实体类就相当于数据库中的数据表,实体类里的属性就相当于数 ...

最新文章

  1. Ubuntu安装python3.7,并将python链接指向python3.7
  2. ES6 系列之 let 和 const
  3. ECUG 早鸟票热卖中 | 大咖聚首 探索云计算下一个十年
  4. Android Studio之提示Unable to delete directory ‘*****\MyApplication\app\build‘
  5. 交互式编程之Golang基本配置(Jupyter-notebooks Golang)
  6. LBP(Local Binary Patterns)局部二进制模式
  7. origin函数绘图_资料|史上最全10套Origin科研必备绘图教学,无需代码
  8. ASP.NET学生考勤管理系统【源码分享】
  9. 【网络覆盖优化】基于matlab的网络覆盖遗传优化问题仿真
  10. 网页游戏开发基础——网页基础知识
  11. 实验三linux进程并发程序设计,实验三Linux进程并发程序设计.doc
  12. [转]使用ArcGIS实现WGS84经纬度坐标到北京54高斯投影坐标的转换
  13. 66个求职应聘技巧性问答(三)
  14. 加ing形式的单词有哪些_初中英语中哪些单词后接动词要加ing形式
  15. 2019中国科学院、中国工程院院士增选名单正式发布
  16. 高三学生早恋怎么处理?家长该怎么做?
  17. 微信小程序商城有什么功能?
  18. 使用switch-case来实现银行存款问题 计算存款利息。有N元,想存M年。有3种方法可选: (1)活期,年利率为r1 0.36% (2)一年期定期,年利率为r2 2.25% 从键盘获取存款年
  19. RuntimeError:a leaf Variable that requires grad has been used in an in-place
  20. ZUCC高级程序设计实验01

热门文章

  1. Autoware 障碍物车辆意图与轨迹预测
  2. U盘和e盘部分文件夹变成.exe文件
  3. filecoin lotus benchmarks v26 GeForce GTX 2080 Ti GeForce GTX 1080 Ti
  4. 计算机网络群名,好听的群名称大全友谊
  5. 《机构投资的创新之路》读书笔记2(第4章):投资组合管理工具
  6. 2006年星座运势全解-巨蟹
  7. 【Bioinfo Blog 007】——Perl与Python的异同整理
  8. 【达梦数据库+下载+安装+可视工具】
  9. android手机版打不开,游戏王决斗链接安卓版打不开 游戏进不去解决方法
  10. 超详细的三星全系列机型线刷图文教程和相关注意操作常识 二