django6/正向查询进阶操作/聚合、分组、F、Q查询/ORM优化/模板层常见字段参数/多对多三种创建方式/

正向查询进阶操作

聚合查询

分组查询

F与Q查询

ORM查询优化

模型层常见字段

ORM常见字段参数

多对多三种创建方式

正向查询进阶操作

1.查询主键为1的书籍对应的出版社名称以及书名

res = models.Publish.object.filter(book_pk=1).values('name','book_title')
#print(res)

2.查询主键为3的书籍对应的作者姓名及书名

res = models.Author.objects.filter(book_pk=1).values('name','book_title')
#print(res)

3.查询jason的作者的电话号码和地址

res = models.AuthorDetail.objects.filter(author_name='jason').values('phone','addr')
#print(res)

4.查询南方出版社出版的书籍名称和价格

res = models.Book.object.fileter(publish_name = '南方出版社').values('title','price')
#print(res)

5.查询jason写过的书的名称和日期

res = models.Book.objects.filter(authors_name='jason').values('title','publish_time')
#print(res)

6.查询电话是110的作者姓名和年龄

res = models.Author.objects.filter(author_detail_phone=110).values('name','age')
#print(res)

7.查询主键为1的书籍对应的作者电话号码

res =models.AuthorDetail.objects.filter(author_book_pk = 1).values('phone')
#print(res)
res = models.Author.objects.filter(book_pk=1).values('author_detail_phone')
#print(res)

聚合查询

聚合函数

函数
max 最大值
min 最小值
sum 计算和
avg 平均值
count 统计
聚合查询
from django.db.models import Max,Min,Sum,Avg,Count
#没有分组之前如何单纯的时候聚合函数,需要关键字aggregate
res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Avg('price'),Count('pk'))
print(res)

分组查询

分组有一个特性,默认只能够直接获取分组的字段,其它字段需要使用方法
我们也可以忽略掉该特性,将sql_mode中only_full_group_by配置移除即可

1.统计每一本书的作者个数

 res = models.Book.objects.annotate(author_num=Count('authors_pk')).values('title','author_num')
 print(res)
    
     res1 = models.Book.objects.values('publish_id').annotate(book_num=Count('pk')).values('publish_id','book_num')
 print(res1)

1.按照整条数据分组

models.Book.objects.annotate() 按照一条条书籍记录分组

2.按照表中的某个字段分组()

models.Book.objects.values('title').annotate() 按照annotate之前values括号中指定的字段分组

2.统计每个出版社卖的最便宜的书的价格

res = models.Publish.object.annotate(min_price=Min('book_price')).values('name','min_price')
#print(res)

3.统计不止一个作者的图书

filter 在annotate前面则是where 在annotate后面则是having

res = models.Book.objects.annotate(author_num=Count('authors_pk')).filter(author_num_gt=1).values('title','author_num')
#print(res)

4.查询各个作者出的书的总价格

res  = models.Author.objects.annotate(book_sum_price = Sum('book_price')).values('name','book_sum_price')
print(res)

F与Q查询

F查询:查询条件不是自定义的而是来自于表中其它字段

from django.db.models import F
#1.查询库存数大于卖出数的书籍
res = models.Book.objects.filter(storage_num_gt=F('sale_num'))
#print(res)

2.将所有书籍的价格上涨1000块

models.Book.objects.update(price=F('price') + 1000)

3.将所有书籍名称加上爆款后缀

models.Book.objects.filter(pk=5).update(title=F('title')+'爆款')#针对字符串数据无法直接拼接

#正确写法
from django.db.models.functions import Concat
from django.db.models import Value
ret3 = models.Book.objects.filter(pk=5).update(titile=Concat(F('title'),Value('爆款')))

ORM查询优化

​ django orm 默认都是惰性查询

​ 当orm的语句在后续的代码中真正需要使用的时候才会执行

​ django orm 自带limit分页

​ 减轻数据库端以及服务端的压力

1.ORM查询优化之only

only会将括号内填写的字段封装成一个个数据对象,对象在点击的时候不会再走数据库查询

但是对象也可以点击括号内没有的字段,只不过每次都会走数据库查询

res = models.Book.objects.only('title','price')
for obj in res:
	print(obj.title)
	print(obj.price)
	print(obj.publish_time)

2.ORM查询优化之defer

defer与only相反

​ 数据对象点击括号内出现的字段,每次都会走数据库查询

​ 数据对象点击括号内的没有的字典,不会走数据库查询

res = models.Book.objects.defer('title','price')
for obj in res:
	#print(obj.title)
	#print(obj.price)
print(obj.publiesh_time)

3.ORM查询优化之select_related

select_related括号内只能接受外键字段(一对多,一对一)自动连表,得出的数据对象在点击表中数据的时候不会再走数据库查询

res = models.Book.object.all()
for obj in res:
	print(obj.publish.name)  #频繁走数据库查询

4.ORM查询优化之prefetch_related

prefetch_related底层其实是子查询,将查询之后的结果也一次性封装到数据对象中,用户在使用的时候感觉不出来

res = models.Book.objects.prefetch_related('publish')
for obj in res:
	print(obj.publish.name)

事务操作

from django.db import  transaction
try:
	with transaction import transaction
	pass #多条ORM语句
except  Exception as e:
print(e)

模型层 ORM常见字段和重要参数


ORM字段和mysql里字段的对应关系。

ORM MYSQL
AutoField() int auto_increment
CharField() 必须提供max_length参数,对应的数据库中是varchar类型
IntergerField() int
DecimalField() decimal
DateField() date
DateTimeField() datetime
BigIntergerField() bigint
BooleanField() 传布尔值 存0和1
TextField() 存储大段文本
FileField() 传文件自动保存到指定位置并存文件路径
EmailField() 本质还是varchar类型

自定义字段类型

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

重要参数

参数 说明
primary_key 主键
max_length 最大字符长度
verbose_name 对应的名字
null 是否可以为空
default 默认值
max_digits 数字允许的最大位数
decimal_places 小数的最大位数
unique 字段的值唯一
db_index 是否为字段设置索引
auto_now 更新修改数据时间
auto_now_add 数据添加的时间
to 设置关联的表
to_field 设置关联的字段
db_constraint 是否创建外键约束,默认True

choice参数:用于可以被列举完全的数据,eg:性别,学历,工作经验,工作状态。

class User(models.Model):
          username = models.CharField(max_length=32)
          password = models.IntegerField()
          gender_choice = (
              (1,'男性'),
              (2,'女性'),
              (3,'变性')
          )
          gender = models.IntegerField(choices=gender_choice)
user_obj.get_gender_display() # 有对应关系就拿 没有还是本身

ps:外键字段中可能还会遇到related_name参数,外键字段中使用related_name参数可以修改正向查询的字段名,之后就可以使用修改后的字段名,类似于起别名。

事务操作


MySQL事务:四大特性(ACID),原子性,一致性,独立性,持久性。一个事务是一个整体,要么同时成功要么同时失败。

mysql开启事务:start transcation;

mysql回滚事务:rollback;

mysql停止事务:commit;

django的事务操作:

from django.db import transaction 
with transaction.atomic():
            pass  # 操作
    
# with一结束事务就结束了,自动提交和回滚

ORM执行原生SQL


方式1

from django.db import connection, connections
cursor = connection.cursor()  
cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
cursor.fetchone()

方式2

models.UserInfo.objects.extra(
                    select={'newid':'select count(1) from app01_usertype where id>%s'},
                    select_params=[1,],
                    where = ['age>%s'],
                    params=[18,],
                    order_by=['-age'],
                    tables=['app01_usertype']
                )

多对多三种创建方式


全自动(常见)

优点:自动创建第三张表

缺点: 第三张表扩展性差

authors = models.ManyToManyField(to='Author')

全手动(使用频率最低)

优点:在于第三张表完全自定义扩展性高,

缺点:在于无法使用外键方法和正反向以及多对多四个方法
3.半自动创建

class Book(models.Model):
    title = models.CharField(max_length=32)
  class Author(models.Model):
    name = models.CharField(max_length=32)
  class Book2Author(models.Model):
    book_id = models.ForeignKey(to='Book')
    author_id = models.ForeignKey(to='Author')

半自动(常见)

优点:正反向还可以使用,并且第三张表扩展性强

唯一的缺陷是不能用add\set\remove\clear四个方法

class Book(models.Model):
    title = models.CharField(max_length=32)
    authors = models.ManyToManyField(
      					to='Author',
    						through='Book2Author',  # 指定表
      					through_fields=('book','author')  # 指定字段
    )
  class Author(models.Model):
    name = models.CharField(max_length=32)
    '''多对多建在任意一方都可以 如果建在作者表 字段顺序互换即可'''
    books = models.ManyToManyField(
      					to='Author',
    						through='Book2Author',  # 指定表
      					through_fields=('author','book')  # 指定字段
    )
  class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    ........
posted @ 2022-09-06 20:13  名字长的像一只老山羊  阅读(42)  评论(0编辑  收藏  举报