官方文档:https://docs.djangoproject.com/zh-hans/2.1/
一、F和Q的用法
1.1 F的字段条件
可以将自己的属性作为条件值
from django.db.models import F
Store.objects.filter(id=F('years')) # 查询Store
案列:
dajango.db.models.F 用于获取字段的值并参于计算或作业更新条件
# 新年:全场水果打8.8折扣
FruitEntity.objects.update(price=F('price') * 0.88)
且还支持运算
Store.objects.filter(id=1).update(years=F('years')+5)
1.2 Q的多条件
可以进行逻辑运算
- & 与 | 或 ~ 非
Store.objects.all().filter(Q(years=1)|Q(years=2))
Store.objects.all().filter(~Q(years=1))
Store.objects.all().filter(Q(years__gt=1)&Q(years__lt=2))
二、原生的SQL语句查询
针对复杂查询来说,通过Queryset查询不是特别方便,则使用原生的SQL查询。
- QuerySet 提供了两种原生SQL查询:
-
QuerySet.raw()
- 要求:查询的字段必须是模型类中声明的字段,且必须存在主键列。查询的结果是RawQuerySet类对象,可以迭代,元素类型是模型类对象。
raw_queryset = FruitEntity.objects.raw('select id, name, price from t_fruit where price< %s order by price desc LIMIT %s, 5',(5,0)) for fruit in raw_queryset: print(fruit)
另外,查询sql语句中可以使用"%s"或“%(name)s”占位符,在其它可以使用元组或字典参数传值
raw_queryset = FruitEntity.objects.raw('select id, name, price from t_fruit where price< %(price)s order by price desc LIMIT %(page)s, 5',{'price':10,'page':0})
-
QuerySet.extra()
extra()扩展查询,针对QuerySet查询结果集中,额外增加查询条件或排序等相关操作。返回的结果还是QuerySet对象。
qs1=FruitEntity.objects.extra(where=['price>%s or name like %s', 'source=%s'], params=['2', '果', '成都']). queryset.all()
-
使用django.db.connection数据库连接对象进行原生SQL查询
connection对象表示与数据库连接的对象,可以通过connection连接对象获取游标cursor再通过cursor的exec cute()/fetchall()/rowcount()相关方法或函数来执行原生的SQL和执行的结果。
from django.db import connection cursor=connection.cursor() cursor.execcute('select * from t_fruit') for row in cursor.fetchall(): print(row)
cursor.execute('update t_fruit set price=2 where id=1')print(cursor.rowcount)connection.commit() #提交更新
》》》from mainapp.models import FruitEntity
1.写出models.CharField字段类的约束
max_length 最大字符个数primary_key 是否为主键 boolunique 是否唯一 boolnull 数据表中的字段值是否为null boolblank 站点表单验证数据时是否为空 booldb_column 指定表中的字段名 strdb_index 是否创建当前字段的索引 boolverbose_name 站点页面显示的字段名称 strdefault 默认值
2.写出模型的Meta元信息有哪些
db_table 指定当前模型类对应的表名 strordering 指定哪些字段的排序方式 ['-字段名',]verbose_name 指定站点显示类的名字 verbose_name_plural 类名称的复数 默认值verbose_name+"s"unique_together 指定哪些字段组合的唯一索引 tuple,如(('字段1'.'字段2'))app_label 指定当前模型所属的app模块名
3.写出QuerySet的filter()查询条件有哪些?
gt gteltltestartwith/isstartwithendswith/iendswithcontains/icontainsin notinisnullisnotnull
三、模型之间的关系
1.设计订单模型
#在models中做类from django.db import modelsclass BaseModel(models.Model): create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) last_time = models.DateTimeField(verbose_name='更新时间', auto_now=True) class Meta: abstract = True # 抽象的模型类,既不会创建表# Create your models here.class OrderModel(BaseModel): num = models.CharField(max_length=20, primary_key=True, verbose_name='订单号') title = models.CharField(max_length=100, verbose_name='订单名称') price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='订单金额') pay_type = models.IntegerField(choices=((0, '余额'), (1, '银行卡'), (2, '微信支付'), (3, '支付宝')), verbose_name='支付方式', default=0) pay_status = models.IntegerField(choices=((0, '待支付'), (1, '已支付'), (2, '待收货'), (3, '已收货'), (4, '完成'), (5, '取消')), verbose_name='订单状态', default=0) receiver = models.CharField(verbose_name='收货人', max_length=20) receiver_phone = models.CharField(max_length=11, verbose_name='收货人的手机') receiver_address = models.TextField(verbose_name='收货人的地址') def __str__(self): return self.title class Meta: db_table = 't_order' verbose_name = verbose_name_plural = '订单表'
def str(self): return self. 对应下面页面
2.在主工程中的settings中注册orderapp
3.在admin.py里注册站点
from django.contrib import adminfrom orderapp.models import OrderModel# Register your models here.class OrderAdmin(admin.ModelAdmin): list_display = ('num', 'title', 'price', 'pay_type', 'pay_status', 'receiver', 'receiver_phone', 'receiver_address') fields = ('num', 'title', 'price', 'pay_type', 'pay_status', 'receiver', 'receiver_phone', 'receiver_address')admin.site.register(OrderModel, OrderAdmin)
4.迁移文件
python manage.py makemigrationspython manage.py migrate
5.运行
python manage.py runserever
3.1扩展:显性方式创建objects
# 声明QuerySet或Manager的子类class OrderManager(models.Manager): # 获取查询结果集对象QuerySet def get_queryset(self): return super().get_queryset().filter(~models.Q(pay_status=5)) # 状态码不是5的objects = OrderManager() # 显性创建 objects
# 统计2018年全年销售总额from orderapp.models import OrderModelfrom django.db.models import SumOrderModel.objects.filter(create_time__year=2022).aggregate(total_price=Sum('price'))
3.2一对一关系
一对一的关系可以通过models.OnetoOneField(关联模型类, on_delete=models.CASCADE)建立
on_delete 除了CASCADE级联删除之外,还有model.SET_NULL级联设置为空
# 用户表的实名认证
class RealProfile(models.Model):
# 声明1对1的关联关系
user = models.OneToOneField(UserEntity, verbose_name='账号', on_delete=models.CASCADE)
real_name = models.CharField(max_length=20,
verbose_name='真实姓名')
number = models.CharField(max_length=18,
verbose_name='证件号')
real_type = models.IntegerField(verbose_name='证件类型',
choices=((0, '身份证'),
(1, '护照'),
(2, '驾驶证')))
image1 = models.ImageField(verbose_name='正面照',
upload_to='user/real')
image2 = models.ImageField(verbose_name='反面照',
upload_to='user/real')
def __str__(self):
return self.real_name
class Meta:
db_table = 't_user_profile'
verbose_name = '实名认证表'
verbose_name_plural = verbose_name
主表:用户表 从表:实名认证表
从表对象获取主表的数据时
from mainapp.models import RealProfile, UserEntity
u1 = RealProfile.objects.filter(real_name='小向').frist()
u1.user.phone # 直接访问主表对象的数据
主表中获取从表的数据
login_u1=UserEntity.objects.get(id=4)
# 对象.关联模型类全小写名称.属性
login_u1.realprofile.number #以隐形的方式读取从表的数据 realprofile 一对一的关系模型类名的名称(全小写)
3.3一对多或多对一的关系 (ForeignKey 一对多)ManytoManyFiled
# 声明水果商品与购物车的关系表
class FruitCartEntity(models.Model):
cart = models.ForeignKey(CartEntity,
on_delete=models.CASCADE,
verbose_name='购物车')
fruit = models.ForeignKey(FruitEntity,
on_delete=models.CASCADE,
verbose_name='水果名')
cnt = models.IntegerField(verbose_name='数量',
default=1)
def __str__(self):
return self.fruit.name + ':' + self.cart.no
# 单价
def price1(self):
# 属性方法在后台显示时没有verbose_name,如果解决?
return round(self.fruit.price, 2) # 从获取主的对象属性
@property # 小计
def price(self):
# 属性方法在后台显示时没有verbose_name,如果解决?
return round(self.cnt * self.fruit.price, 2)
class Meta:
db_table = 't_fruit_cart'
verbose_name = verbose_name_plural = '购物车详情表'
# 从读取主对象的信息 def price1(self): # 属性方法在后台显示时没有verbose_name,如果解决? return round(self.fruit.price, 2) # 从获取主的对象属性 # 主对象读取多个从对象的信息login_u = UserEntity.objects.get(id=5)#查询当前用户的购物车中的所有商品及数量相关的信息cart_fruits = login_u.cartentity.**fruitcartentity_set**.all()for fruit_cart in cart_fruits: print(fruit_cart.fruit.name, fruit-cart.fruit.price, fruit_cart.cnt)
3.4 多对多
models.ManyToManyFiled
作业:
1.练习今天的知识点
2.完成订单模型类的拆分(多个模型)及相关模型
3.预习:
-
模型类的面向对象
-
模板语法