zoukankan      html  css  js  c++  java
  • 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:py27Django_projectDjangoModel>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:py27Django_projectdjangomodel>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("动物获取成功")
    

    作业

    • 做一个班级学生列表
      • 班级列表
      • 班级列表可点击
      • 点击的时候显示班级所有学生
  • 相关阅读:
    spring mvc全局异常处理
    spring mvc URL忽略大小写
    easyui datagrid 加载两次请求,触发两次ajax 请求 问题
    根据多列去除重复记录,保留具有特殊列值的行,去除其他行
    ibatis 批量插入oracle总结
    ibatis 参数错误,无效字符
    jvm 原理和优化
    tomcat 内存问题 xms xmx permsize maxPermsize
    java 中与 或 非 异或 和位移运算
    项目jar包管理,使用 .userlibraries 文件增加jar包的可移植性,明确jar包依赖,多项目共用jar包里
  • 原文地址:https://www.cnblogs.com/yihutu/p/11986256.html
Copyright © 2011-2022 走看看