Django 一、模型models 继承django.db.models.Model
1.模型字段 / 模型字段选项参考:
官网:https://docs.djangoproject.com/zh-hans/3.2/ref/models/fields/#common-model-field-options
2.模型Meta选项(定义模型类的属性):
csdn: https://blog.csdn.net/bbwangj/article/details/79967858
官网:https://docs.djangoproject.com/zh-hans/3.2/ref/models/options/
3.模型属性
Manger 无自定义的Manger ,默认是Objects,是Django模型和数据库查询操作之间的接口。通过模型类来访问,必能通过模型实例来访问。 (表级操作)
4.模型方法 (行级操作)
在模型中添加自定义方法,或者复写原来的方法。
_str ()
get_absolute_url()
可以在save/delete前后,做些额外的事情
Save()
Delete()
def save(self, *args, **kwargs):
do_something()
super().save(*args, **kwargs) # Call the "real" save() method.
do_something_else()
5.模型继承
(1)抽象基类:
创建基类,使用meta中的abstract,不会创建数据表,继承该基类,会获取该类中的字段
class Meta:
abstract = True
(2)多表继承
每个子类模型创建一张新表。
(3)代理模型
修改/添加模型的方法。继承模型类,通过Meta的proxy,设置代理模型。MyPerson和Person使用同一张表
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
# ...
pass
(4)多重继承
Django 二、执行查询
1.创建对象 (save/create)
s = Student(name='myName')
s.save()
或一步创建
Blog.objects.create(name="Blog1", tagline="this is a blog1.")
2.修改对象
a = Blog.objects.all().first()
a.name = 'Blog2'
a.save()
保存ForeignKey字段
a.student = Student.object.get(id=1)
a.save()
保存ManyToManyField字段
b1=Blog.objects.get(id=2)
b2=Blog.objects.get(id=3)
b3=Blog.objects.get(id=4)
s.blog.add(b1,b2,b3)
3.检索对象
QuerySet代表来自数据库中对象的一个集合, 类似于select语句
Filter 给定参数,缩小查询结果量。类似于where或limit
(1)查全部:Student.objects.all()
(2)过滤器检索
filter(**kwargs) 满足给定查询参数
exclude(**kwargs) 不满足给定查询参数
链式过滤器:student.objects.filter(xxxx).exclude(xxxxxx).filter(xxxxxx)
每个QuerySet都是唯一的:
q1=student.objects.filter(条件1) 满足条件1的querySet
q2=q1...exclude(条件2) 满足条件1和不满足条件2的querySet
q3=q1.filter(条件3) 满足条件1和条件3的querySet
QuerySet是惰性的:创建QuerySet不会引发数据库活动,只有被计算是才执行查询操作
q=student.objects.filter(xxxx)
q=q.exclude(xxxxxx)
q=q.filter(xxxxxx)
Print(q) 开始执行查询
(3)使用get()检索单个对象
没有满足条件时,抛DoesNotExist异常
匹配多个对象,抛MultipleObjectsReturned异常
(4)其他QuerySet方法
Order_by()
Reverse()
Distinct()
Values()
Value_list()
Select_related()
Union() 并集
Intersection() 交集
Difference() 差集
......
官网:https://docs.djangoproject.com/zh-hans/3.2/ref/models/querysets/#queryset-api
(5)限制QuerySet条目数
对QuerySet进行切片操作,禁止对其进行进一步排序或过滤
Student.objects.all[:5]
Student.objects.all[5:10]
(6)字段查询
以关键字参数传递给QuerySet方法,格式:field__lookuptype=value
exact :关键字参数不包含__,类型会指定为exact。
Blog.objects.get(id__exact=2)
Blog.objects.get(id=2)
iexact:不分大小写的匹配
Blog.objects.get(name__iexact='blog1')
Contains: 大小写敏感的包含测试
Blog.objects.get(name__contains='b') ===>like '%b%'。 会自动转义其中的%和下划线
startswith, endswith: 以......开头和以......结尾的查找。
istartswith, iendswith: 以......开头和以......结尾的查找,大小写不敏感。
In/gt/gte/lt/lte/range/date/year/month/day/isnull/regex/iregex.........
官网:https://docs.djangoproject.com/zh-hans/3.2/ref/models/querysets/#field-lookups
(7)跨关系查询
Entry.objects.filter(blog__name='Blog1')
Entry.objects.filter(blog__name_contains='Blog')
(8)跨多值关联
要注意链式过滤器的结果
(9)过滤器为模型指定字段 (F表达式)
模型字段值与另一个字段进行比较
F表达式,支持对F()对象进行加减乘除等操作,F()中也能用__,关联关系查询,对于date/datetime可以加减一个timedelta对象,支持位操作。
Entry.objects.filter(updateTime__gt=F('addTime')+timedelta(day=3))
(10)主键(pk)查询快捷方式
Student.object.get(id__exact=2)
Student.object.get(id=2)
Student.object.get(pk=2)
关于用id查询的都可以用pk代替
(11)缓存和QuerySet
尽量保存QuerySet,来复用,触发计算全部的查询结果集,保证结果填入缓存。之后用的都是缓存中的。
以下动作可以触发计算全部的查询结果集:
[i for i in queryset]
bool(queryset)
i in queryset
List(queryset)
4.查询JSONField
使用JSONField字段, 可以使用JSONField来准确查找数据。
创建:
from django.db import models
class Dog(models.Model):
name = models.CharField(max_length=200)
data = models.JSONField(null=True)
def __str__(self):
return self.name
保存和查询None值:
Dog.objects.create(name='Max',data=None)
Dog.objects.filter(data__isnull=True). ===>Max
可以将字典中的key或数组的index作为查询名,进行Json内部数据的查询。
Dog.objects.create(name='Rufus', data={
... 'breed': 'labrador',
... 'owner': {
... 'name': 'Bob',
... 'other_pets': [{
... 'name': 'Fishy',
... }],
... },
... })
<Dog: Rufus>
Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': None})
<Dog: Meg>
Dog.objects.filter(data__breed='collie')
<QuerySet [<Dog: Meg>]>
Dog.objects.filter(data__owner__name='Bob')
<QuerySet [<Dog: Rufus>]>
Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
<QuerySet [<Dog: Rufus>]>
包含与键查找:
Contains: 查询data中包含{'owner':'Bob'}的Dog
Dog.objects.filter(data__contains={'owner': 'Bob'})
Contained_by: 查询data中包含{'owner':'Bob'}或{'breed':'collie'}的Dog
Dog.objects.filter(data__contained_by={'breed': 'collie', 'owner': 'Bob'})
Has_key: 查询data的key中有owner的Dog
Dog.objects.filter(data__has_key='owner')
Has_keys:查询data的key中有owner和breed的Dog
Dog.objects.filter(data__has_keys=['breed', 'owner'])
Has_keys:查询data的key中有owner或breed的Dog
Dog.objects.filter(data__has_any_keys=['owner', 'breed'])
5.通过Q对象完成复杂查询
Q对象(django.db.models.Q)可以压缩关键字参数集合,通过&,|,括号,~连接起来。
查询函数filter(),exclude(),get()可以接受一个或多个Q对象参数
如果有Q对象,必须位于所有关键字参数之前。
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who',
)
6.比较对象
使用==,实际比较的是两个模型实例的主键值。
some_entry == other_entry
some_entry.id == other_entry.id
7.删除对象
e.delete(),删除对象,并返回被删除对象的个数和对象类型的字典。
querySet的delete()方法,批量删除querySet中的对象,但是要注意不会调用复写的delete()方法。
关联对象也会删除,由外键的on_delete参数指定。
8.一次修改多个对象
querySet的update()方法,批量更新数据,不会调用模型的save(),可以使用F表达式
Entry.objects.all().update(number_of_pingbacks=F('number_of_pingbacks') + 1)
9.关联对象
模型中定义了关联关系(ForeignKey,OneToOneField,ManyToManyField),可以快速访问关联对象。
Blog中有多个Entry
(1)一对多关联:
正向访问:
e = Entry.objects.get(id=2)
e.blog = some_blog
e.save()
反向访问:
b = Blog.objects.get(id=1)
b.entry_set.all() # Returns all Entry objects related to Blog.
b.entry_set is a Manager that returns QuerySets.
b.entry_set.filter(headline__contains='Lennon')
b.entry_set.count()
关联对象的其他方法:
Add(obj1,obj2......) 添加
Create(**kwargs)。 创建一个新对象,并加入关联对象集合中
Remove(obj1,obj2,...) 从关联对象集合中删除
Clear() 清空关联对象集合
Set(objs) 替换关联对象集合. b.entry_set.set([e1,e2])
(2)多对多关联:
可以加上'_set'
....
通过设置related_name
(3)一对一关联
Django 三、聚合
1.在QuerySet上生成聚合
Aggregate() 输出值是QuerySet的终端子句,字典
from django.db.models import Avg
Book.objects.all().aggregate(Avg('price'))
简化为
Book.objects.aggregate(Avg('price'))
Book.objects.aggregate(average_price=Avg('price')) 提供聚合值的名称
聚合函数:
AVg, Count, Max, Min, StdDev, Sum, Variance
官网:https://docs.djangoproject.com/zh-hans/3.2/ref/models/querysets/#aggregation-functions
2.为QuerySet中的每一条目生成聚合
Annotate()子句 注解 , 输出值是QuerySet
Book和Author是多对多的关系
Book.object.annotate(Count('authors')) 查询出各个书的作者的数量
提供聚合值的名称
Book.objects.annotate(num_authors=Count('author'))
3.组合多个聚合
使用distinct参数
q = Book.objects.annotate(Count('authors', distinct=True), Count('store', distinct=True))
q[0].authors__count
2
q[0].store__count
3
4.和filter, exclude连用,进行复杂的查询操作,,不过要注意顺序