hello world

人生若只如初见

Django(5)--model 2

Django-model(2)

模型查询

查询集表示从数据库获取的对象合集

查询集可以有多个过滤器

过滤器就是一个函数,基于所给的参数限制查询集结果

从SQL角度来说,查询集合和select语句等价,过滤器就像where条件

查询集和过滤器(queryset)

在管理器上调用方法返回查询集

查询经过过滤器筛选后返回新的查询集,所以可以写成链式调用

返回查询集的方法称为过滤器

all() 返回所有数据

filter() 返回符合条件的数据

exclude() 过滤掉符合条件的数据

order_by() 排序,默认根据ID排序,id大的在前-id

values() 一条数据就是一个字典,返回一个列表

def get_persions(request):
    persion = Person.objects.all().order_by("-id")
    persion = Person.objects.all().order_by("p_age")
    context = {
        "persion":persion,
    }
    return render(request,'persion_list.html',context=context)
def get_persions(request):
    persion = Person.objects.all().order_by("p_age")
    persion_values = persion.values()
    print(type(persion_values),persion_values)
    context = {
        "persion":persion,
    }
    return render(request,'persion_list.html',context=context)

结果返回一个列表,列表中都是字典,方便以后转json:
<class 'django.db.models.query.QuerySet'> <QuerySet [{'id': 15, 'p_name': 'Tom8', 'p_age': 13, 'p_sex': True, 'p_hobby': None}, {'id': 22, 'p_name': '小明', 'p_age': 15
, 'p_sex': True, 'p_hobby': None}, {'id': 3, 'p_name': 'Tom16', 'p_age': 16, 'p_sex': False, 'p_hobby': None}, {'id': 19, 'p_name': 'Tom12', 'p_age': 19, 'p_sex': True,
 'p_hobby': None}, {'id': 11, 'p_name': 'Tom4', 'p_age': 27, 'p_sex': True, 'p_hobby': None}, {'id': 10, 'p_name': 'Tom3', 'p_age': 30, 'p_sex': False, 'p_hobby': None}
, {'id': 7, 'p_name': 'Tom0', 'p_age': 42, 'p_sex': False, 'p_hobby': None}, {'id': 14, 'p_name': 'Tom7', 'p_age': 42, 'p_sex': False, 'p_hobby': None}, {'id': 9, 'p_na
me': 'Tom2', 'p_age': 43, 'p_sex': True, 'p_hobby': None}, {'id': 18, 'p_name': 'Tom11', 'p_age': 47, 'p_sex': True, 'p_hobby': None}, {'id': 16, 'p_name': 'Tom9', 'p_a
ge': 48, 'p_sex': False, 'p_hobby': None}, {'id': 4, 'p_name': 'Tom49', 'p_age': 49, 'p_sex': True, 'p_hobby': None}, {'id': 21, 'p_name': 'Tom14', 'p_age': 49, 'p_sex'
: True, 'p_hobby': None}, {'id': 8, 'p_name': 'Tom1', 'p_age': 60, 'p_sex': False, 'p_hobby': None}, {'id': 13, 'p_name': 'Tom6', 'p_age': 61, 'p_sex': True, 'p_hobby':
 None}, {'id': 2, 'p_name': 'Tom62', 'p_age': 62, 'p_sex': False, 'p_hobby': None}, {'id': 1, 'p_name': 'Tom69', 'p_age': 69, 'p_sex': True, 'p_hobby': None}, {'id': 12
, 'p_name': 'Tom5', 'p_age': 70, 'p_sex': False, 'p_hobby': None}, {'id': 17, 'p_name': 'Tom10', 'p_age': 74, 'p_sex': False, 'p_hobby': None}, {'id': 5, 'p_name': 'Tom
79', 'p_age': 79, 'p_sex': True, 'p_hobby': None}, '...(remaining elements truncated)...']>
def get_persions(request):
    persion = Person.objects.all().order_by("p_age")
    persion_values = persion.values()
    print(type(persion_values),persion_values)
    for persion_value in persion_values:
        print(persion_value)
    context = {
        "persion":persion,
    }
    return render(request,'persion_list.html',context=context)
结果:
{'id': 15, 'p_name': 'Tom8', 'p_age': 13, 'p_sex': True, 'p_hobby': None}
{'id': 22, 'p_name': '小明', 'p_age': 15, 'p_sex': True, 'p_hobby': None}
{'id': 3, 'p_name': 'Tom16', 'p_age': 16, 'p_sex': False, 'p_hobby': None}
{'id': 19, 'p_name': 'Tom12', 'p_age': 19, 'p_sex': True, 'p_hobby': None}
{'id': 11, 'p_name': 'Tom4', 'p_age': 27, 'p_sex': True, 'p_hobby': None}

返回单个数据

get():返回一个满足条件的对象(要注意)

如果没有找到符合条件的对象,会引发模型类.DoesNotExist异常,如果找到多个,会引发模型类.MultiObjectsResturned异常

first():返回查询集中的第一个对象

last():返回查询集中的最后一个对象

count():返回当前查询集中的对象个数

exists():判断查询集中是否有数据,如果有数据返回True没有反之

状态码(扩展)

  • 2xx
    • 请求成功
  • 3xx
    • 转发或重定向
  • 4xx
    • 客户端错误
  • 5xx
    • 服务器错了
    • 后端开发人员最不想看到的

获取单个对象(get)

  • 查询条件没有匹配的对象,会抛异常,DoesNotExist
  • 如果查询条件对应多个对象,会抛异常,MultipleObjectsReturned
from django.conf.urls import url
from App import views
urlpatterns = [
    url(r'^addpersions/',views.add_persions),
    url(r'getpersions/',views.get_persions),
    url(r'^addperson',views.add_person),
    url(r'^getperson/',views.get_person),

]
def get_person(request):
    #person = Person.objects.get(p_age=66)
    #如果有两个47
    person = Person.objects.get(p_age=47) 
    print(person)
    return HttpResponse("获取成功")

first和last

  • 默认情况下可以正常从queryset中获取
  • 隐藏bug,可能会出现first和last获取到的是相同的对象
    • f方法:显示,手动写排序规则
def get_person(request):
    #第一个人
    person = Person.objects.all().first()
    print(person.p_name)
    # 最后一个人
    person_one = Person.objects.all().last()
    print(person_one.p_name)
    return HttpResponse("获取成功")

新建startApp Two

from django.conf.urls import url
from Two import views
urlpatterns = [
    url(r'^getuser',views.get_user),

]
from django.db import models

# Create your models here.
class User(models.Model):
    u_name = models.CharField(max_length=16,unique=True)
    u_password = models.CharField(max_length=256)
def get_user(request):
    username = "Sunck"
    password = "120"
    users = User.objects.filter(u_name = username)
    print(users.count())
    if users.count():
        user = users.first()
        if user.u_password == password:
            print('获取用户信息成功')
        else:
            print('密码错误')
    else:
        print('用户不存在')
    return HttpResponse('获取成功')
  • count判断
def get_user(request):
    username = "dd"
    password = "120"
    users = User.objects.filter(u_name = username)
    print(users.count())
    if users.count():
        user = users.first()
        if user.u_password == password:
            print('获取用户信息成功')
        else:
            print('密码错误')
    else:
        print('用户不存在')
    return HttpResponse('获取成功')
结果:
Quit the server with CTRL-BREAK.
0
用户不存在
[02/Dec/2019 16:50:32] "GET /Two/getuser HTTP/1.1" 200 12
def get_user(request):
    username = "Sunck"
    password = "1234"
    users = User.objects.filter(u_name = username)
    print(users.count())
    if users.count():
        user = users.first()
        if user.u_password == password:
            print('获取用户信息成功')
        else:
            print('密码错误')
    else:
        print('用户不存在')
    return HttpResponse('获取成功')
结果:
Quit the server with CTRL-BREAK.
1
密码错误
[02/Dec/2019 16:51:45] "GET /Two/getuser HTTP/1.1" 200 12
  • exists 直接判断
def get_user(request):
    username = "Sunck"
    password = "120"
    user = User.objects.filter(u_name = username)
    print(user.count())
    if user.count():
        user = users.first()
        if user.u_password == password:
            print('获取用户信息成功')
        else:
            print('密码错误')
    else:
        print('用户不存在')
    return HttpResponse('获取成功')

结果:
Quit the server with CTRL-BREAK.
1
密码错误
[02/Dec/2019 16:54:54] "GET /Two/getuser HTTP/1.1" 200 12

限制查询集和查询集的缓存

限制查询集,可以使用下标的方法进行限制,等同于SQL中的limit

studentlist = student.objects.all()[0:5] 下标不能是负数

查询集的缓存:每个查询集都包含一个缓存,来最小化对数据库的访问

在新建的查询集中,缓存首次为空,第一次对查询集求值,会发生数据缓存,Django会将查询出来的数据做一个缓存,并返回查询结构,以后的查询直接使用查询集的缓存。

切片

  • 和python中的切片不太一样
  • queryset[5:15] 获取第5条到第15条数据
    • 相当于SQL语句中的limit和offset

缓存集

  • filter
  • exclude
  • all
  • 都不会真正的去查询数据库
  • 只有我们在迭代结果集,或者获取单个对象属性的时候,它才会去查询数据库
  • 懒查询
    • 为了优化我们的结构和查询
from django.conf.urls import url
from Two import views
urlpatterns = [
    url(r'^getuser/',views.get_user),
    url(r'^getusers/',views.get_users),

]
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Userlist</title>
</head>
<body>
<h3>Userlist</h3>
<hr>
<ul>
    {% for users in users %}
    <li>姓名:{{ users.u_name }}</li>
    {% endfor %}
</ul>
</body>
</html>
def get_users(request):
    users = User.objects.all()[1:3] #左闭右开
    # print(users)
    context = {
        "users":users
    }
    return render(request,'users_list.html',context=context)

字段查询

对sql中where的实现,作为方法filter(),exclude(),get()的参数

语法:属性名称__比较运算符=值

外键:属性名_id

转义:like语句中使用%是为了匹配占位符,匹配数据中的%(where like '%')

filter(sname__contains='%')

查询条件(比较运算符)

  • 属性__运算符=值
  • exact:判断,大小写敏感,filter(isDelete = False)
  • contains 类似于模糊查询 like,是否包含,大小写敏感,filter(sname__contains='王')
  • startwith 以xx开始 本质也是like,以values开头或结尾,大小写敏感
  • endwith 以xx结束,本质也是like

以上4个在运算符前加上 i(ignore)忽略就不区分大小写了 iexact...

  • isnull,isnotnull:是否为空,filter(sname__isnull=False)

  • in 在某个集合中,是否包含在范围内,filter(pk__in=[2,5,6])

  • gt,gte,lt,lte:大于,大于等于,小于,小于等于 filter(sage__gt=30)

时间的:

  • year,month,day,week_day,hour,minute,second:

  • filter(lasttime__year=2017)

  • Django中查询条件有时区问题

    • 关闭Django中自定义的时区

      • settings.py
      USE_TZ = False
      
    • 在数据库中创建对应的时区表

  • models.py 验证时间属性

class Order(models.Model):
    o_num = models.CharField(max_length=16,unique=True)
    #auto_now_add自动加时间
    o_time = models.DateTimeField(auto_now_add=True)
G:\py27\Django_project\DjangoModel>python manage.py shell
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from Two.models import Order
>>> order = Order()
>>> order.o_num = '110'
>>> order.save()
>>> order = Order()
>>> order.o_num = '120'
>>> order.save()
>>> order = Order()
>>> order.o_num = '111'
>>> order.save()

Two/urls.py

from django.conf.urls import url
from Two import  views
urlpatterns = [
  url(r'^getorder/',views.get_orders),
]
from django.shortcuts import render,HttpResponse
from Two.models import Order

# Create your views here.
def get_orders(request):
    orders = Order.objects.filter(o_time__year=2020)
    for order in orders:
        print(order.o_num)
    return HttpResponse('获取成功')
def get_orders(request):
    # month月份不会打印数据是时区问题,在settings.py中关闭时区就可以打印了
    orders = Order.objects.filter(o_time__month=12)
    for order in orders:
        print(order.o_num)
    return HttpResponse('获取成功')

查询快捷:

  • pk:代表主键,filter(pk=1)

跨关系查询:

  • 模型类名__属性名__比较运算符,实际上就是处理的数据库中的join
  • grade = Grade.objects.filter(stduent__sconted__contains='晓强')
    • 描述中带有'晓强'这两个字的数据属于哪个班级

直接根据学生的信息查询班级

class Grade(models.Model):
    g_name = models.CharField(max_length=16)

class Student(models.Model):
    s_name = models.CharField(max_length=16)
    s_grade = models.ForeignKey(Grade)
from django.conf.urls import url
from Two import views
urlpatterns = [
    #url(r'^getuser/',views.get_user),
    #url(r'^getusers/',views.get_users),
    url(r'getgrades/',views.get_grades),
]

def get_grades(request):
    #根据级联数据的信息查询,跨关系查询
    grades = Grade.objects.filter(student__s_name = 'Jack')
    for grade in grades:
        print(grade.g_name)
    return HttpResponse('获取成功')

聚合函数

使用 aggregate()函数返回聚合函数的值

  • Avg:平均值
  • Count:数量
  • Max:最大值
  • Min:最小值
  • Sum:求和

student.objects().aggregate(max('sage'))

class Customer(models.Model):
    c_name = models.CharField(max_length=16)
    c_cost = models.IntegerField(default=10)
E:\py27\Django_project\djangomodel>python manage.py shell
Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from Two.models import Customer
>>> for i in range(10):
...     customer = Customer()
...     customer.c_cost = i
...     customer.c_name = "C%d" %i
...     customer.save()
...
>>> exit()
def get_customer(request):
    #Max要倒包,Djangodb中的
    ret = Customer.objects.aggregate(Max('c_cost'))
    #ret = Customer.objects.aggregate(Avg('c_cost')) #获取平均
    print(ret)
    return HttpResponse('花费成功')

F对象

  • 可以获取我们属性的值

  • 可以实现一个模型的不同属性的运算操作

  • 还可以支持算数运算

  • 可以使用模型的A属性与B属性进行比较

  • grades = Grade.objects.filter(ggirlnum__gt=F('gboynum'))

  • F对象支持算数运算符

grades = Grade.objects.filter(ggirlnum__gt=F('gboynum')+10)

class Conpany(models.Model):
    c_name = models.CharField(max_length=16)
    c_gril_num = models.IntegerField(default=5)
    c_boy_num = models.IntegerField(default=3)
from django.conf.urls import url
from Two import views
urlpatterns = [
   # url(r'^getuser/',views.get_user),
    # url(r'^getusers/',views.get_users),
    # url(r'getgrades/',views.get_grades),
    # url(r'getcustomer/',views.get_customer),
    url(r'getconpany',views.get_conpany),
from django.db.models import Max, Avg, F, Q
def get_conpany(request):
    #男生比女生少
    #conpays = Conpany.objects.filter(c_boy_name__lt=F('c_gril_num'))
       #女生比男生多15以上
    conpays = Conpany.objects.filter(c_boy_name__lt=F('c_gril_num')-15)
    for conpay in conpays:
        print(conpay.c_name)
    return HttpResponse("获取公司成功")

Q对象

  • 条件封装
  • 可以对条件进行封装
  • 封装之后,可以支持逻辑运算(与、或、非)
  • 过滤器的方法中的关键字参数,常用于组合条件
  • 年龄小于25
  • Student.objects.filter(Q(sage__lt=25))
  • Q对象语法支持| (or),&(and),~(取反)
  • 年龄大于等于的
  • Student.objects.filter(~Q(sage__lt=25))
from django.db.models import Max, Avg, F, Q
def get_conpany(request):
    # conpays = Conpany.objects.filter(c_boy_name__gt=1).filter(c_gril_num=5)
    # conpays = Conpany.objects.filter(Q(c_boy_name__gt=1) & Q(c_gril_num__gt=5))
    conpays = Conpany.objects.filter(Q(c_boy_name__gt=1) | Q(c_gril_num__gt=5))
    for conpay in conpays:
        print(conpay.c_name)
    return HttpResponse("获取公司成功")

模型成员

  • 类属性

    • 显性:开发者自己写的那些
    • 隐形:objects是一个Manager类型的一个对象,作用于数据库进行交互(开发者没有书写,orm自动生成)
      • 如果你把隐形属性手动声明了,系统就不会为你产生隐形属性了
  • 当模型类没有指定管理器的时候,Djang会自动为我们创建模型管理器

    • 当然我们也可以自定义管理器,

      class Student(models.Model):
          stuManager = models.Manager()
      
    • 当自定义模型管理器时,objects就不存在了,Django就不会为我们自动生成模型管理器

class Animal(models.Model):
    a_name = models.CharField(max_length=16)
from django.conf.urls import url
from Two import views
urlpatterns = [
    # url(r'^getuser/',views.get_user),
    # url(r'^getusers/',views.get_users),
    # url(r'getgrades/',views.get_grades),
    # url(r'getcustomer/',views.get_customer),
    #url(r'getconpany',views.get_conpany),
    url(r'getanimals/',views.get_animals),
def get_animals(request):
    animals = Animal.objects.all()
    for animal in animals:
        print(animal.a_name)
    return HttpResponse('动物获取成功')
  • 隐性变显性
class Animal(models.Model):
    a_name = models.CharField(max_length=16)
    a_m = models.Manager()
def get_animals(request):
    animals = Animal.a_m.all()
    for animal in animals:
        print(animal.a_name)
    return HttpResponse('动物获取成功')
class Animal(models.Model):
    a_name = models.CharField(max_length=16)
    #is_delete是否删除,重要的数据做逻辑删除
    is_delete = models.BooleanField(default=False)
    a_m = models.Manager()
# 加属性要迁移数据库
python manage.py makemigrations
python manage.py migrate
  • 删了狗

def get_animals(request):
    animals = Animal.a_m.filter(is_delete = False)
    for animal in animals:
        print(animal.a_name)
    return HttpResponse('动物获取成功')
# 查不到狗了

自定义管理器类

模型管理器是Django的模型与数据库进行交互的接口,一个模型可以有多个模型管理器

自定义模型管理器作用:

  • 可以向管理器中添加额外的方法
  • 修改管理器返回的原始查询集
  • 提供创建对象的方式
class StudentManager(models.Manager):
    def get_queryset(self):
        return
    super(StudentManager,self).get_queryset.filter(isDelete=False)
    def createStudent(self):
        stu= self.mode()
        #设置属性
        return stu
class AnimalManager(models.Model):
    def get_queryset(self):
        return super(AnimalManager,self).get_queryset().filter(is_delete=False)
  • 增量改属性
class Animal(models.Model):
    a_name = models.CharField(max_length=16)
    #is_delete是否删除,重要的数据做逻辑删除
    is_delete = models.BooleanField(default=False)
    objects = AnimalManager()
def get_animals(request):
    animals = Animal.a_m.all()
    animals = Animal.objects.all()
    for animal in animals:
        print(animal.a_name)
    return HttpResponse("动物获取成功")
# 增加create方法
class AnimalManager(models.Model):
    def get_queryset(self):
        return super(AnimalManager,self).get_queryset().filter(is_delete=False)
    def create_animal(self,a_name ="Chicken"):
        a = self.model()
        a.a_name = a_name
        return a
def get_animals(request):
    animals = Animal.a_m.all()
    for animal in animals:
        print(animal.a_name)
    Animal.objects.create_animal()#调用create方法
    return HttpResponse("动物获取成功")

作业

  • 做一个班级学生列表
    • 班级列表
    • 班级列表可点击
    • 点击的时候显示班级所有学生

posted on 2019-12-04 22:35  一壶兔  阅读(282)  评论(0编辑  收藏  举报

导航