• Django之模型层


    orm常用的字段

    AutoField
    这个字段是代表我键的这个字段是自增的,而且里面必须要填priamry_key=True这个参数
    
    CharField
    这个就等于数据库里面的varchar()但它里面必须要填max_length这个参数来标识字符长度
    
    IntegerField
    是一个整数类型,范围在2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存,)
    
    DateField日期字段,里面有可以放参数,其中auto_now代表的是只要操作数据,其时间也会跟着变,auto_now_add代表的是只有创建的时候,才会创建时间,后面怎么改记录,时间都不会变,一般都是auto_now_add
    
    DecimalField()可以控制小数的,max_digits表示总共几位,decimal_places=表示小数占几位

    字段中的参数

    null 表示这个字段可以为空
    unique  如果设置为true就跟数据库中一样,表示唯一
    db_index   为true表示为该字段设置索引
    default 设置默认值
    
    DateField和DateTimeField
    
    auto_now  表示数据修改,我的时间也会跟着修改
    auto_now_add 表示只有数据在创建的时候,我的时间也会跟着创建,但后面数据怎么修改,我都不会变
    
    关系字段ForeignKey
    
    to 设置要关联的表
    to_field 设置要建立的外键字段,不填,默认是和关联的表的主键建立外键字段
    
    on_delete  表示当删除表中的数据的时候,其和关联的表的行为
    
    on_constranit 是否在数据库中创建外键约束,默认是true

    一对一

    OnetoOneField

    多对多

    ManyToManyField

    单表的增删改查

    1.单表操作
    create_time = models.DateField()
    关键性的参数
    1.auto_now:每次操作数据 都会自动刷新当前操作的时间
    2.auto_now_add:在创建数据的时候 会自动将创建时间记录下来 后续的修改不会影响该字段

    在django中我们可以自定义一个测试文件,在里面写测试脚本,不需要再视图操作模型表那么麻烦了

     这样就可以直接运行你的test.py文件来运行测试

    必知必会13条

    all()查询出所有

     filter(**kwargs):包含了所有与筛选条件匹配的对象,就是一个列表里面套对象,没有就是一个空

     get是只获取一个也是对象本身,如果没有则会报错

    exclude(**kwargs):取反,它包含了所有与筛选条件不匹配的内容

     values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列

    values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

    order_by(*field): 对查询结果排序

    reverse(): 对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。

    distinct(): 从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。)

    first()表示返回匹配懂啊的第一个记录

    last表示返回匹配到的最后一个记录

    count(): 返回数据库中匹配查询(QuerySet)的对象数量。

    exists(): 如果QuerySet包含数据,就返回True,否则返回False

    总结:

    返回queryset对象的有:

    all()

    filter()

    exclude()

    order_by()

    reverse()

    distinct()

    特殊的queryset

    value返回是一个字典序列

    value_list返回是一个元祖序列

    返回具体对象

    get()

    first()

    last()

    布尔值

    exists()

    返回数字的方法有

    count()

    Django打印sql语句有2种方式

    一种是有约束的,就是queryset对象可以通过query这个方法查看相对应的sql语句

    第二种是无限制的,只要你执行了表的语句,都会打印相应的sql语句,就是在settings中配置一下,具体如下:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }

     神奇的双下划线用法:

    原本我们查找是这样的
    models.User.objects.filer(age=10)
    现在我要求大于20的怎么弄呢,不能>,当有这种特殊的需求的时候,就要用到双下划线了
    __gt 大于
    __lt 小于
    __gte 大于等于
    __lte 小于等于
    
    __in  代表在不在里面,一个集合
    
    __range 是什么到什么的关系,也就是一个闭区间
    
    模糊查询,也就是判断包含不包含
    __contains 这个识别大写小写
    __icontains 这个忽略大小写
    
    —startswith这个判断以什么开头
    
    __endswith 这个是以什么结尾
    
    __year  按年查询

    多表查询

    一对多字段的增删改查

    增:
    publish_id传数字
    models.Book.objects.create(title='三国演义',price=189.99,publish_id=1)
    publish直接传出版社对象
    publish_obj = models.Publish.objects.filter(pk=2).first()
    models.Book.objects.create(title='红楼梦',price=999.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)
    
    
    删除
    models.Publish.objects.filter(pk=2).delete()  # 默认都是级联更新 级联删除

    多对多增删改查

    前提都是将要给增删改查的对象先找出来,然后再对象点那个虚拟字段后面跟方法来完成增删改查。
    增
    
    book_obj = models.Book.objects.filter(pk=1).first()
    
    print(book_obj.authors)  # 对象点击多对多虚拟字段 会直接跨到多对多的第三张表
    book_obj.authors.add(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)
    book_obj.authors.add(author_obj1,author_obj2)
    小结:
    add()
     是给书籍添加作者  括号内既可以传数字也可以传对象
    并且支持一次性传多个  逗号隔开即可
    改
    
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.set([2,])
    book_obj.authors.set([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.set([author_obj,])
    book_obj.authors.set([author_obj, author_obj1, author_obj2])
    小结:
    set()
    括号内必须是一个可迭代对象,可迭代对象里面可以是数字,也可以是对象,但记着不要混合用
    
    删除
    
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.remove(3)
     book_obj.authors.remove(1,2)
     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.remove(author_obj)
    book_obj.authors.remove(author_obj1,author_obj2)
    小结:
    remove()即支持数字,也支持对象,也可以传多个
    将关系全部清空用clear()即可
    book_obj.authors.clear()不用传参

    跨表查询(重点!!!)

    正向查询和反向查询(重点!!!)

    正向与方向的概念解释
    
    一对一
    正向:author---关联字段在author表里--->authordetail        按字段
    反向:authordetail---关联字段在author表里--->author        按表名小写
     查询jason作者的手机号   正向查询
    查询地址是 :山东 的作者名字   反向查询
      
    一对多
    正向:book---关联字段在book表里--->publish        按字段
     反向:publish---关联字段在book表里--->book        按表名小写_set.all() 因为一个出版社对应着多个图书
    
    多对多
     正向:book---关联字段在book表里--->author        按字段
    反向:author---关联字段在book表里--->book        按表名小写_set.all() 因为一个作者对应着多个图书

    基于双下划线的跨表查询(连表查询,就不再2行代码了,而是一行了)

    # 一对一
    -连表查询
            -一对一双下划线查询
                -正向:按字段,跨表可以在filter,也可以在values中
                -反向:按表名小写,跨表可以在filter,也可以在values中
        # 查询jason作者的手机号   正向查询  跨表的话,按字段
        # ret=Author.objects.filter(name='jason').values('authordetail__phone')
        # 以authordetail作为基表 反向查询,按表名小写  跨表的话,用表名小写
        # ret=AuthorDetail.objects.filter(author__name='jason').values('phone')
        
        # 查询jason这个作者的性别和手机号
        # 正向
        # ret=Author.objects.filter(name='jason').values('sex','authordetail__phone')
    
        # 查询手机号是13888888的作者性别
        # ret=Author.objects.filter(authordetail__phone='13888888').values('sex')
        # ret=AuthorDetail.objects.filter(phone='13888888').values('author__sex')
        
    """
    总结 其实你在查询的时候先把orm查询语句写出来,再看用到的条件是否在当前表内,在就直接获取,不在就按照正向按字段反向按表名来查即可
    比如:
        1.查询出版社为北方出版社的所有图书的名字和价格
        res1 = Publish.objects.filter(name='').values('book__name','book__price')
        res2 = Book.objects.filter(publish__name='').values('name','price')
        2.查询北方出版社出版的价格大于19的书
        res1 = Publish.objects.filter(name='',book__price__gt=19).values('book__name','book__price)
    """

    聚合查询

    aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。
    
    键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。
    用到的内置函数:
    from django.db.models import Avg, Sum, Max, Min, Count
    示例:
    >>> from django.db.models import Avg, Sum, Max, Min, Count
    >>> models.Book.objects.all().aggregate(Avg("price"))
    {'price__avg': 13.233333}
    还可以为聚合函数指定一个名称
    >>> models.Book.objects.aggregate(average_price=Avg('price'))
    {'average_price': 13.233333}

    分组查询

    from django.db.models import Avg
    
    res = models.Book.objects.annotate(别名=聚合函数).values(别名,其他内容)
    values是获取某个表中的某个字段

    F与Q查询

    F查询就是通过数据库获取某个字段对应的值

    from django.db.models import F
    models.Book.objects.filter(priice=F(price)

    Q查询就是修改查询的条件的。

    from django.db.models import Q
    res = models.Book.objects.filter(title='三国演义',price=444.44)  # filter只支持and关系
    res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444))  如果用逗号 那么还是and关系
    res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444))
    res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444))

    高级Q用法

    q = Q()
    q.connector = 'or'  # 修改查询条件的关系   默认是and
    q.children.append(('title__contains','三国演义'))  # 往列表中添加筛选条件
    q.children.append(('price__gt',444))  # 往列表中添加筛选条件
    res = models.Book.objects.filter(q)  # filter支持你直接传q对象  但是默认还是and关系
    print(res)

     自定义Char字段

           class MyChar(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                                     

    查询优化

    only 和 defer
    
    
    这2个都是查出来是一个列表套对象,但不一样的是,only如果获取的是括号内指定的字段,会直接获取,如果获取的不是指定的字段,那么会频繁的访问数据库。而defer则正好相反,如果获取的是指定的字段,那么会频繁的访问数据库,如果不是指定的字段则是会直接获取。
    
    
    
    select_related  和 prefect_related
    
    都是做连表操作的。
    
    括号内都只能放外键字段,并且可以连续用__连外键字段,并且只支持一对多核一对一。
    不同处:select_related这个是直接连表,而prefect_related则是现将这个外键字段对应的id值拿到,然后再用这个id值去另外关联的表中找到一一对应的值。

    注意:orm中的语句操作,全部都是惰性查询,就是只有在真正需要这个数据的时候,才会去访问数据库,减少数据库的压力

    事务

        from django.db import transaction
        
            with transaction.atomic():
                """数据库操作
                在该代码块中书写的操作 同属于一个事务
                """
                models.Book.objects.create()
                models.Publish.objects.create()
                # 添加书籍和出版社 就是同一个事务 要么一起成功要么一起失败
            print('出了 代码块 事务就结束')
  • 相关阅读:
    Sybase自增字段跳号的解决方法
    sybase从表A创建表B
    timed out waiting for input: auto-logout
    关闭归档提示:ORA-38774: cannot disable media recovery
    vmware下给linux添加硬盘
    oracle 双机热备,oracle dataguard 和oracle rac的区别和联系(转)
    with admin option 与with grant option
    Python yield 使用浅析
    支持向量机的优缺点
    PCA MATLAB
  • 原文地址:https://www.cnblogs.com/xinfan1/p/11545501.html
Copyright © 2020-2023  润新知