说明 紧接python django实践
聚合和分组查询 聚合查询(aggregate)
1 2 3 4 5 from django.db.models import Avg,Max,Min,Count,Sum # 引入函数 ... res = models.Book.objects.aggregate(Avg("price")) print(res, type(res)) ...
1 2 res=models.Book.objects.aggregate(c=Count("id"),max=Max("price"),min=Min("price")) print(res,type(res)
分组查询(annotate)
分组查询一般会用到聚合函数,所以使用前要先从 django.db.models
引入 Avg,Max,Min,Count,Sum(首字母大写)
1 from django.db.models import Avg,Max,Min,Count,Sum # 引入函数
返回值:
分组后,用 values 取值,则返回值是 QuerySet 数据类型里面为一个个字典;
分组后,用 values_list 取值,则返回值是 QuerySet 数据类型里面为一个个元组。
MySQL 中的 limit 相当于 ORM 中的 QuerySet 数据类型的切片。
annotate 里面放聚合函数。
values 或者 values_list 放在 annotate 前面: values 或者 values_list 是声明以什么字段分组,annotate 执行分组。
values 或者 values_list 放在annotate后面: annotate 表示直接以当前表的pk执行分组,values 或者 values_list 表示查询哪些字段, 并且要将 annotate 里的聚合函数起别名,在 values 或者 values_list 里写其别名。
实例
1 2 3 4 res = models.Publish.objects.values("name").annotate(in_price = Min("book__price")) print(res) <QuerySet [{'name': '菜鸟出版社', 'in_price': Decimal('100.00')}, {'name': '明教出版社', 'in_price': Decimal('300.00')}]>
1 2 3 4 res = models.Book.objects.annotate(c = Count("authors__name")).values("title","c") print(res) <QuerySet [{'title': '菜鸟教程', 'c': 1}, {'title': '吸星大法', 'c': 1}, {'title': '冲灵剑法', 'c': 1}]>
1 2 res = models.Book.objects.filter(title__startswith="菜").annotate(c = Count("authors__name")).values("title","c") print(res)
1 2 3 4 res = models.Book.objects.annotate(c = Count("authors__name")).filter(c__gt=0).values("title","c") print(res) <QuerySet [{'title': '菜鸟教程', 'c': 1}, {'title': '吸星大法', 'c': 1}, {'title': '冲灵剑法', 'c': 1}]>
根据一本图书作者数量的多少对查询集 QuerySet 进行降序排序:
1 2 res = models.Book.objects.annotate(c = Count("authors__name")).order_by("-c").values("title","c") print(res)
1 2 res = models.Author.objects.annotate(all = Sum("book__price")).values("name","all") print(res)
F() 查询
F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值
F 动态获取对象字段的值,可以进行运算。
Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取余的操作。
修改操作(update)也可以使用 F() 函数。
实例
1 2 3 4 from django.db.models import F ... book=models.Emp.objects.filter(salary__gt=F("age")).values("name","age") ...
1 2 res = models.Book.objects.update(price=F("price")+100) print(res)
Q() 查询
实例
查询价格大于 350 或者名称以菜开头的书籍的名称和价格。
1 2 3 4 from django.db.models import Q res=models.Book.objects.filter(Q(price__gt=350)|Q(title__startswith="菜")).values("title","price") print(res)
查询以”菜”结尾或者不是 2010 年 10 月份的书籍:
1 2 res = models.Book.objects.filter(Q(title__endswith="菜") | ~Q(Q(pub_date__year=2010) & Q(pub_date__month=10))) print(res)
查询出版日期是 2004 或者 1999 年,并且书名中包含有”菜”的书籍。
1 2 res = models.Book.objects.filter(Q(pub_date__year=2004) | Q(pub_date__year=1999), title__contains="菜") print(res)
Q 对象和关键字混合使用,Q 对象要在所有关键字的前面:
中间件-验证登录
StudyDjanog/TestModel/model.py
加入user
1 2 3 4 class Users(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32)
1 2 python manage.py makemigrations TestModel python manage.py migrate TestModel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 def user_login(request): if request.method != "POST": return JsonResponse({'code': -1, 'msg': 'method must is POST'}) data = json.loads(request.body) user_name = data.get('username') pwd = data.get("pwd") print(data) try: user_entry = Users.objects.get(name=user_name, pwd=pwd) if user_entry: # 设置登录的session request.session["user"] = user_name return JsonResponse({'code': 1, 'msg': 'login is success'}) except ObjectDoesNotExist: return JsonResponse({'code': -1, 'msg': 'login is fail111'})
编写中间件 TestModel\middleware\authen.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 from django.http import JsonResponse from django.shortcuts import redirect,render from django.utils.deprecation import MiddlewareMixin import re #白名单 #将登陆、登出、验证登陆请求设为白名单,不进行用户验证。 #这里设置了/static/静态文件,因为我这个项目静态文件没走nginx,如果静态文件通过nginx访问,可以不需要设置 exclued_path = ["/login/","/testModel/login/","/logout/","/login_ajax_check","/static/"] #用来验证用户是否有权限登陆的中间件 class AuthenticationMiddle(MiddlewareMixin): def process_request(self, request): url_path = request.path #如果不在请求在白名单里 if url_path not in exclued_path: #如果未登陆,则调转到登陆页面,将请求的url作为next参数 # if not request.user.is_authenticated: if not request.session.get("user"): # return redirect("/login/?next={url_path}".format(url_path=url_path)) return JsonResponse({'code': -1, 'msg': 'login is failed2222'}) #如果已经登陆,则通过 else: pass
引用中间件 StudyDjanog\StudyDjanog\settings.py
1 2 3 4 5 6 7 8 9 10 11 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'TestModel.middleware.authen.AuthenticationMiddle', # 引用自定义中间件 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import requests data ={"username": "admin", "pwd": "123456"} rs = requests.session() resp = rs.post("http://127.0.0.1:8000/testModel/login/", json=data) print(resp.text) resp1 = rs.get("http://127.0.0.1:8000/testModel/userQuery") print(resp1.text) {"code": 1, "msg": "login is success"} <p>runoob runoob </p>
最终的session内容在django_session表中自动存储了
其他