orm真实存在的字段名与虚拟字段名
book_obj = models.Book.objects.filter(pk=1).first() book_obj.publish_id = 3 # 点表中真实存在的字段名 book_obj.save()
publish_obj = models.Publish.objects.filter(pk=2).first() book_obj.publish = publish_obj # 点orm中字段名 传该字段对应的表的数据对象 book_obj.save()
orm中既可以使用真实存在字段名来进行增删改查,
也可以通过虚拟字段后面跟上虚拟字段外键表的数据对象,来进行增删改查,本质这个对象就是外键表数据的id,虚拟字段对应的就是表中的真实字段(如:user_id)
ORM中对象点的正反查询
#多对多字段的反向查询 author_obj = models.Author.objects.filter(name='jason').first() print(author_obj.book_set) # app01.Book.None print(author_obj.book_set.all()) #一对一字段的反向查询 authordetail_obj = models.AuthorDetail.objects.filter(phone=110).first() print(authordetail_obj.author.name)
正向查询点虚拟字段名,
当查询的结果为一个对象时不需要加all()(出现于一对一)
当查询的结果为多个对象时需要加all(),也就是列表里面套对象,不然会报错(# app01.Author.None)(出现于一对多,多对多)
反向查询点要查的表名小写
当查询的结果为一个对象时:
要查的表名小写,且不需要加all()(出现于一对一)
当查询的结果为多个对象时:
要查的表名小写_set.all()),也就是列表里面套对象,不然会报错(# app01.Author.None)(出现于一对多,多对多)
ORM中双下划线的正反查询
res = models.Book.objects.filter(title='三国演义').values('authors__authordetail__phone') #先正向在反向,接着是反向中的列名 print(res)
正向查询:
虚拟字段__虚拟字段对应表的列名
反向查询:
表名小写__表中的列名
···查询出版社为东方出版社的所有图书的名字和价格 # 正向 res = models.Publish.objects.filter(name='东方出版社').values('book__title','book__price') print(res) # 反向 res = models.Book.objects.filter(publish__name='东方出版社').values('title','price') print(res)
正向查询(思路):
以出版社为基表查询
反向查询(思路):
以书为基表查询
注意:
数据的增删改查都是按基表来
book__price__gt=400(书的价格大于400)
ORM中聚合查询与分组查询
# 聚合查询 aggregate from django.db.models import Max,Min,Count,Sum,Avg # 查询所有书籍的作者个数 res = models.Book.objects.filter(pk=3).aggregate(count_num=Count('authors')) print(res) # 查询所有出版社出版的书的平均价格 res = models.Publish.objects.aggregate(avg_price=Avg('book__price')) print(res) # 统计东方出版社出版的书籍的个数 res = models.Publish.objects.filter(name='东方出版社').aggregate(count_num=Count('book__id')) print(res) #聚合查询:一般用于取值(如多少个数),用法同分组查询 # 分组查询(group_by) annotate # 统计每个出版社出版的书的平均价格 res = models.Publish.objects.annotate(avg_price=Avg('book__price')).values('name','avg_price') print(res) #统计每一本书的作者个数 res = models.Book.objects.annotate(count_num=Count('authors')).values('title','count_num') #这里的authors虚拟字段对应的就是表中的真实字段(authors_id) #每一本这样的条件就用分组查询,基表就是书的表,如果没有values默认按基表进行分组,展现出来的是基表中一本书对应的作者个数,如果有values按values进行分组 #注意分组的时候,Count(),values()里面的是以基表为主 print(res) #统计出每个出版社卖的最便宜的书的价格 res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price') #这里book__price,也就是统计条件也可以是正反向查询 print(res) # 查询每个作者出的书的总价格 res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price') print(res)
单表查询的补充
res = models.User.objects.exclude(name='jason') #exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 res = models.User.objects.order_by('age').reverse() #reverse(): 对查询结果反向排序 ( 前面要先有排序才能反向) res = models.User.objects.all().exists() # exists(): 如果QuerySet包含数据,就返回True,否则返回False res1 = models.User.objects.filter(name='jason',age=3).exists() res = models.User.objects.values('name','age').distinct() # distinct(): 从返回结果中剔除重复纪录 去重的对象必须是完全相同的数据才能去重 # 神奇的双下划线查询 # 查询年轻大于44岁的用户 res = models.User.objects.filter(age__gt=44) # 查询年轻小于44岁的用户 res = models.User.objects.filter(age__lt=44) # 查询年轻大于等于44岁的用户 res = models.User.objects.filter(age__gte=44) # 查询年轻小于等于44岁的用户 res = models.User.objects.filter(age__lte=44) # 查询年龄是44或者22或者73的用户 res = models.User.objects.filter(age__in=[44,22,73]) # 查询年龄在22到44范围内 res = models.User.objects.filter(age__range=[22,44]) # 查询名字中包含字母n的用户 res = models.Author.objects.filter(name__contains='n') # sqlite数据库不支持这种查法 res = models.User.objects.filter(name__icontains='e') # 无视大小写 # 查询名字以j开头的用户 res = models.User.objects.filter(name__startswith='j') # 查询名字以n结尾的用户 res = models.User.objects.filter(name__endswith='n') # 查询年份 res = models.Book.objects.filter(publish_date__year=2019) # sqlite数据库不支持这种查法
一对多,多对多的增删改补充
# 一对多的增删改 # 增 models.Book.objects.create(title='红楼梦',price=66.66,publish_id=1) publish_obj = models.Publish.objects.filter(pk=2).first() models.Book.objects.create(title='三国演义',price=199.99,publish=publish_obj) # 改(两种方法) models.Book.objects.filter(pk=1).update(publish_id=3) publish_obj = models.Publish.objects.filter(pk=2).first() models.Book.objects.filter(pk=1).update(publish=publish_obj) book_obj = models.Book.objects.filter(pk=1).first() book_obj.publish_id = 3 # 点表中真实存在的字段名 book_obj.save() publish_obj = models.Publish.objects.filter(pk=2).first() book_obj.publish = publish_obj # 点orm中字段名 传该字段对应的表的数据对象 book_obj.save() # 删(两种放法) models.Book.objects.filter(pk=1).delete() book_obj = models.Book.objects.filter(pk=3).first() book_obj.delete() #多对多的增删改 # 增:add支持传数字或对象,并且都可以传多个 #给书籍绑定与作者之间的关系 book_obj = models.Book.objects.filter(pk=3).first() book_obj.authors.add(1) #.authors是拿当前对象跨到第三张多对多表,前面的对象当做表中第一个值 book_ob j.authors.add(2,3) author_obj = models.Author.objects.filter(pk=1).first() author_obj1 = models.Author.objects.filter(pk=3).first() book_obj.authors.add(author_obj) book_obj.authors.add(author_obj,author_obj1) #改(重置):set 可以传数字和对象,并且支持传多个,但传的必须是可迭代对象!!! # 修改书籍与作者的关系 book_obj = models.Book.objects.filter(pk=3).first() book_obj.authors.set((1,)) book_obj.authors.set((1,2,3)) author_list = models.Author.objects.all() book_obj = models.Book.objects.filter(pk=3).first() book_obj.authors.set(author_list) #删:remove可以传数字和对象,并且支持传多个,如果传的是列表需要打散 # 删除书籍与作者的绑定关系 book_obj = models.Book.objects.filter(pk=3).first() book_obj.authors.remove(1) book_obj.authors.remove(2,3) author_list = models.Author.objects.all()) book_obj.authors.remove(*author_list) # 需要将queryset打散 # 清空 :清空的是你当前这个表记录对应的绑定关系 book_obj = models.Book.objects.filter(pk=3).first() book_obj.authors.clear()
注:当对象点普通字段时才save(),其他不需要
补充
模板语法: {%for foo in l %} {% if forloop.first %} <p>这是第一次</p> {% elif forloop.last %} <p>这是最后一次</p> {% else %} <p>{{foo}}</p> {% endif %} {% emdif %} <p>给的是空啊,没法循环</p> {% endfor %} 自定义char类型字段: class MyCharField(models.Field): 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): return 'char(%s)'%self.max_length HTTP响应状态码 1XX:服务器成功接收到数据正在处理 你可以继续提交数据 2XX:请求资源成功(200) 3XX:内部重定向(django里面redirect)(301,302) 4XX:请求资源不存在(404) 5XX:服务器内部错误(服务端错误 代码出bug了 服务器机房着火了...500) #url后面不带/,会匹配两次 第一次没匹配上 会让浏览器加一个/再访问一次(默认为trun) APPEND_SLASH = True 静态文件路径配置 settings: STATIC_URL=‘/xxx/’ STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static'), ] HTML: {% load static %} <script src='{% static "myjs.js" %}'></script> <link rel="stylesheet" href="{% static 'mycss.css'%}"> 反向解析(带参数的) url(r'^indexxasdaskkdjlasdasdasdasdadasksajdlksaj/(?P<xxx>d+)/', index,name='index'), 有名无名均按照下面方式使用即可 前端拿到url:{% url 'index' 1 %} 后端拿到url: from django.shortcuts import HttpResponse,render,reverse def index(request,xxx): print(reverse('index',args=(1,)) return render(request,'test.html')