测试环境

  1. import os
  2. if __name__ == "__main__":
  3. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings")
  4. import django
  5. django.setup()
  6. 下面继续书写脚本代码

前识回顾:

import os

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings")
    import django
    django.setup()
    from app91 import models
    import datetime
    #增
    # 方式一
    # models.User.objects.create(name='wyy',age=19,register_time='2021-2-8 8:00:00')
    #方式二
    # user_obj = models.User(name='lili',age=56,register_time=datetime.datetime.now())
    # user_obj.save()

    # 删
    # 方式一
    # models.User.objects.filter(pk =1).delete()
    # 方式二
    # user_obj = models.User.objects.filter(pk = 1).first()
    # user_obj.delete()

    # 改
    # 方式一
    # models.User.objects.filter(pk = 1).update(name='lala')
    # 方式二
    # user_obj = models.User.objects.get(pk = 1) #该方法不推荐使用,如果pk不存在则会直接报错,而filter则不会
    # user_obj.name = 'heihei'
    # user_obj.save()

查看内部sql语句的方式
.query 只能用于queryset

通用方式:在配置内加配置

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

必会13条

# 1.all()   查询所有
    # 2.filter  带有过滤条件的查询
    # 3.get       直接拿数据对象,条件不存在时直接报错
    # 4.first     拿queryset内第一个元素
    # 5.last      拿queryset内最后一个元素
    # 6.values      拿取一个或多个字段对应的值
        # models.User.objects.values('name','age')
        # 类似于 select name,age from ...;
        #返回的是[{},{}]
    # 7.values_list
        # models.User.objects.values_list()
        #返回的是[(),()]
    # 8.distinct    去重,要把主键排除在外,否则无法去重
        # models.User.objects.values('name','age').distinct()
    # 9.order_by    排序
        # models.User.objects.order_by('age') #默认升序
        # models.User.objects.order_by('-age') #降序
    # 10.reverse    反转的前提是数据已经排序
    # 11.count      统计个数
        #models.User.objects.all().count()
    # 12.exclude    排除某个在外
        # models.User.objects.exclude(name='wyy')
    # 13.exists     判断是否存在

双下划线查询

# models.User.objects.filter(age__gt=20)  大于
    # models.User.objects.filter(age__lt=20)  小于
    # models.User.objects.filter(age__lte=20) 小于等于
    # models.User.objects.filter(age__gte=20) 大于等于
    # models.User.objects.filter(age__in=[10,20,30]) 查询年龄是10,20,30的数据
    # models.User.objects.filter(age__range=[10,30])  查询年龄在10-30之间的数据,收尾兼顾
    # models.User.objects.filter(name__contains='n')  查询名字包含n的数据  区分大小写
    # models.User.objects.filter(name__icontains='n')  查询名字包含n的数据  忽略大小写
    # models.User.objects.filter(name__endswith='w')  查询名字以w结尾的数据,startwith同理
    # models.User.objects.filter(register_time__year='2021')  查询时间以年份为单位查询,月、日.....同理

外键增删改查


    #外建增删改查

    # 一对多

    # 增
    # models.Book.objects.create(titlle='',price='',publish_id=值)
    # models.Book.objects.create(titlle='',price='',publish=对象)

    # 删
    # models.Publish.objects.filter().delete()  级联删除

    # 修改
    #     修改一样可以和增加一样直接给值或者给对象



    # 多对多   第三张关系表的增删改查

    # 增
    # 书籍表和作者表
    # Book_obj = models.Book.objects.filter(pk=1).first()
    # 
    # Book_obj.authors.add(1,2)  主键为1的书籍添加作者主键为1和2,以此操作第三张表
    # 
    # author_obj = models.author.objects.filter(pk= 1).first()
    # Book_obj.authors.add(author_obj)  对象可放多个
    # 
    # add:给第三张关系表添加数据,括号内既可以传值,也可以传对象,支持多个
    # 
    # 
    # 
    # 
    # 删
    # 
    # Book_obj.authors.remove(1,2)  同样支持传值和对象
    # 
    # remove 第三张关系表删除数据,括号内既可以传值,也可以传对象,支持多个
    # 
    # 
    # 改
    # 
    # Book_obj.authors.set([1,2])
    # 
    # set  括号内必须是可迭代对象,既可以是对象也可以是值,同样支持多个
    #     先删除,后新增的方式修改
    # 
    # 
    # 清空
    # 
    # 在第三张表内清空两者绑定关系
    # 
    # Book_obj.authors.clear()  清空Book_obj绑定的所有关系

正反向的跨表查询


正反向概念
    看外键字段在哪张表,有外键字段查询没有外键字段的,为正向,反之则为反向


正向查询按字段
反向查询按表名小写

跨表查询
    基于对象(子查询)

    正向
    查询书籍主键为1的出版社
    Book_obj = models.book.objects.filter(pk=1).first()
    Book_obj.publish.all().name   获取出版社名字   能拿到多个,则要.all()
    Book_obj.publish.addr   获取出版社地址


    反向
    查询出版社出版了哪些书
    publish_obj =  models.Publish.objects.filter(name='北京出版社').first()
    publish_obj.book_set.all()



    总结:
    当反向查询结果有多个需要在表名后加_set.all(),一个则不需要


    基于双下划线(联表查询)

    查询书籍主键为1的出版社名称和书的名称

    models.book.objects.filter(pk =1).values('title','publish__name')
        title 在book表内直接写,出版社名称在另外一张表,直接publish__name
    models.Publish.objects.filter(book__id=1).values('name','book__title')

    上述正反向结果一致

    查询书籍主键为1的作者的电话号码
    models.Book.objects.filter(pk=1).values('author__author_detail__phone')

聚合查询

# 聚合查询              aggregate(单独使用的时候用的关键字)
from django.db.models import Min,Max,Sum,Count,Avg

from app91 import models
models.Book.objects.aggregate(Avg('price'),Max('price'),Min('price'),Count('pk'),Sum('price'))

分组查询

分组查询   annotate
models.Book.objects.annotate()  按书分组
models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')

models.Book.objects.values('price').annotate()   按照表中指定字段进行分组

分组查询如果出错,记得查看严格模式

F与Q查询

F查询

from django.db.models import F
models.Book.objects.filter(salesnum__gt=F('inventory'))  查询销售数量大于库存数量的书籍

models.Book.objects.update(price=F('price')+10)  给书籍表中所有书籍价格加10



Q查询

from django.db.models import Q

models.Book.objects.filter(Q(salesnum__gt=100),Q(price__gt=20))   默认and关系
models.Book.objects.filter(Q(salesnum__gt=100)|Q(price__gt=20))   or关系
models.Book.objects.filter(~Q(salesnum__gt=100)|Q(price__gt=20))  非关系


Q高阶用法
q=Q()
q.connector='or'   改成or连接
q.children.append('salenum__gt',100)
q.children.append('price__gt',20)
models.Book.objects.filter(q)   等同于上面的and关系查询

django中开启事务

from django.db import transaction
with transaction.atomic():
    sql1
    sql2
    sql3.....
    with下书写的sql都属于同一个事务

choices参数

# choices参数
#     只要某个字段可能性能列举完全的,一般情况下都会采用choices参数
#

class User(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    gender_choices =(
        (1,'男'),
        (2,'女'),
        (3,'其他'),
    )
    gender = models.IntegerField(choices=gender_choices)

    #gender中存到数字在上面的gender_choices中,会自动匹配到对应关系
    #不在范围内照样存储
    models.User.objects.filter(pk=1).first().get_gender_display()
    取值方法:get_XXX_display()   XXX为字段名
    如果没有对应关系则直接返回存储的值