【Django知识点】模型层

【Django知识点】模型层

  • 1.配置数据库
    • 1.1 创建数据库
    • 1.2 settings中配置mysql
  • 2 模型类
    • 2.1 模型类格式
    • 2.3 表名配置
    • 2.4 常用字段类型
    • 2.5 字段约束
  • 3 单表查询
    • 3.1 创建测试数据
      • 3.1.1.定义User模型
      • 3.1.2.生成数据迁移并执行迁移文件
      • 3.1.3.创建user表数据
      • 3.1.4.user表内容如下
    • 3.2 查询方法
      • 3.2.1 格式与方法
      • 3.2.2 返回单一对象 get(条件)
      • 3.2.3 返回所有对象 all()
      • 3.2.4 返回满足条件的对象 filter(条件)
      • 3.2.5 返回不满足条件的对象 exclude(条件)
      • 3.2.6 存在、个数与索引
    • 3.3 查询条件
      • 3.3.1 格式与关键字
      • 3.3.2 判断相等 = 或 exact
      • 3.3.3 模糊查询 contains|startswith|endswith
      • 3.3.4 为空查询 isnull
      • 3.3.5 范围查询 in
      • 3.3.6 比较查询 gt gte lt lte
      • 3.3.7 日期查询 year month day hour minute second
      • 3.3.8 字段比较 F
      • 3.3.9 逻辑比较 Q
    • 3.4 排序 order_by()
    • 3.5 聚合aggregate()
  • 4 增删改
    • 4.1 save()
    • 4.2 create()
    • 4.3 update()
    • 4.4 delete()
  • 5 多表操作
    • 5.1 外键种类
    • 5.2 外键的常用参数
    • 5.3 一对多
      • 5.3.1 案例
      • 5.3.2 引用关系
    • 5.4 多对多(django维护中间表)
    • 5.5 多对多(自己维护中间表)
    • 5.6 多对一自关联
    • 5.7 多表查询
  • 6 自定义管理器

1.配置数据库

1.1 创建数据库

create database test1;

1.2 settings中配置mysql

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': 'localhost',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': '12345',
        'NAME': 'test1',
    }
}

2 模型类

2.1 模型类格式

在app的models中

from django.db import models
class Stu(models.Model):
    class Meta():
        db_table = 't_stu'						# 表名
    id = models.AutoField(primary_key=True)		# id int primary key auto_increment
    username = models.CharField(max_length=30)	# username varchar(30)

2.3 表名配置

假如app的名字是commen
【Django知识点】模型层_第1张图片
数据库中的表名:

  • 如果设置Meta中的db_table,表名为db_table
  • 如果不设置,表名为【app名字】_【类名小写】(例如上图:commen_stu)

2.4 常用字段类型

关键字 说明
AutoField 自动增长的整数(相当于:int auto_increment)
 说明:
  常用的参数:primary_key=True(定义主键)
  如果不写id=models.AutoField(primary_key=True),django也会创建一个自增的主键id
IntegerField 整数 int
FloatField 浮点数
 必填参数:
  max_digits:最大总位数
  decimal_places:小数位数
Decimal 定点数
 必填参数:
  max_digits:最大总位数
  decimal_places:小数位数
CharField 字符串 varchar()
 必填参数:
  max_length:最大长度
TextField 大文本 Text
BooleanField True|False
NullBooleanField null|True或|False
DateField 日期 Date: YYYY-MM-DD(常用参数):
  auto_now:每次修改对象,自动设置时间
  auto_now_add:第一次被创建,自动设置时间
DateTimeField 日期 Datetime: YYYY-MM-DD HH:MM:SS(常用参数):
  auto_now:每次修改对象,自动设置时间
  auto_now_add:第一次被创建,自动设置时间
TimeField 时间:Time:HH:MM:SS
EmailFiled 邮箱
ImageField 图片

例如:

from django.db import models
class Student(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)

2.5 字段约束

关键字 说明 默认值 是否要迁移修改表结构
primary_key 是否是主键 False
null 能否为空 False
unique 能否重复 False
default 默认值
blank 在django管理后台新增或编辑一条表数据时,该字段能否为空
null是数据库范畴,blank是表单验证范畴
False
db_column 表字段名称 属性名称
choices 在django管理后台新增或编辑一条表数据时,显示为下拉框
from django.db import models
class Student(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16,unique=True)

3 单表查询

3.1 创建测试数据

注:增删改后面会详细说明
【Django知识点】模型层_第2张图片

3.1.1.定义User模型

from django.db import models
from hashlib import md5
import datetime

# 用户模型类
class User(models.Model):
    account = models.CharField(max_length=16,unique=True)                 # 登录账号
    username = models.CharField(max_length=16,null=True,db_index=True)    # 用户昵称
    _password = models.CharField(max_length=32)                           # 密码,使用md5加密
    gender = models.IntegerField(default=0)                               # 性别,0:男,1:女
    birthday = models.DateField(null=True)                                # 生日
    money = models.DecimalField(max_digits=10,decimal_places=2,default=0) # 余额,总位数10,小数位2,默认0
    email = models.EmailField(null=True)                                  # 邮箱
    image = models.ImageField(null=True)                                  # 头像
    createDatetime = models.DateTimeField(auto_now_add=datetime.datetime.now())   # 创建时间
    updateDatetime = models.DateTimeField(auto_now=datetime.datetime.now())       # 最近一次修改时间
    isdelete = models.BooleanField(default=False)                         # 逻辑删除
	
    @property
    def password(self):
        return self._password

    @password.setter
    def password(self,password):
        self._password = md5(password.encode('ascii')).hexdigest()def __str__(self):
		return 'User对象—> id=%s,username=%s' % (self.id,self.username)

# 创建user表数据
def build_user(num = 100):
    for i in range(num):
        User.objects.create(
            account = '%05d' % i,
            username = 'name%s' % i,
            password = str(i),
            gender = i % 2,
            birthday = datetime.datetime.now() + datetime.timedelta(days=i),
            money = i ** 2 + 12.34 * i + 100,
            email = '%[email protected]' % i,
            createDatetime=datetime.datetime.now(),
            updateDatetime=datetime.datetime.now(),
            isdelete=i % 2,
        )

3.1.2.生成数据迁移并执行迁移文件

python manage.py makemigrations
python manage.py migrate

3.1.3.创建user表数据

python manage.py shell

>>  from  【app名字】.models import *
>>  build_user()

3.1.4.user表内容如下

【Django知识点】模型层_第3张图片

3.2 查询方法

3.2.1 格式与方法

查询格式:

  • 【模型类名】.objects.【方法】(【条件】)
方法 说明
get(字段名=值) 返回一个满足条件的对象,如果有多个对象满足条件,报异常
all() 返回所有数据
filter(条件) 返回条件的数据
exclude(条件) 返回不满足条件的数据

返回结果:

  • get()返回模型类的类对象
  • all()、filter()、exclude()返回QuerySet

QuerySet的特点:

  1. 允许多个对象满足条件,可以迭代
  2. 允许没有对象满足条件(此处对比get)
  3. 拥有一些对象方法

QuerySet的对象方法:

方法 说明
count() 返回结果的总条数
first() 返回第一个对象
last() 返回最后一个对象
exists() 判断查询集中是否有数据,返回True|False
order_by(【字段1】,-【字段】) 先根据【字段1】升序排列,然后根据【字段2】降序排列
[start,end] 分页

3.2.2 返回单一对象 get(条件)

注意:

  • 必须返回一个对象,如果多个对象满足查询条件、或没有满足条件的对象,都会报异常。
user1 = User.objects.get(id=1)
print(user1)
try:
	User.objects.get(id=10000) 		# 没有id=10000的对象
except:print('没有满足条件的对象,抛出异常')
try:
	User.objects.get(isdelete=0) 	# 多个对象满足条件
except:print('多个对象满足条件,抛出异常')

'''【结果】
>>  User对象—> id=1,username=name0
>>  没有满足条件的对象,抛出异常
>>  多个对象满足条件,抛出异常
'''

3.2.3 返回所有对象 all()

user_s = User.objects.all()

print('user_s的类型是:',type(user_s))
for user in user_s:
	print(user)

'''【结果】
>>  user_s的类型是: 
>>  User对象—> id=1,username=name0
>>  User对象—> id=2,username=name1
>>  User对象—> id=3,username=name2
>>  ... ...
>>  ... ...
'''

3.2.4 返回满足条件的对象 filter(条件)

user_s = User.objects.filter(id=1)
print('user_s的类型是:',type(user_s))
print(user_s)

'''【结果】
>>  user_s的类型是: 
>>   id=1,username=name0>]>
'''

3.2.5 返回不满足条件的对象 exclude(条件)

# 查询id不为1的user对象
user_s = User.objects.exclude(id=1)

3.2.6 存在、个数与索引

user_s = User.objects.exclude(id=1)

ret_exists = user_s.exists()			# 结果集是否有数据
ret_count = user_s.count()				# 结果集中数据个数
ret_first = user_s.first()				# 结果集中第一个数据
ret_last = user_s.last()				# 结果集中最后一个数据
ret_1_10 = user_s[1:10]					# 结果集切片,不支持负索引
print('ret_exists=',ret_exists)
print('ret_count=',ret_count)
print('ret_first=',ret_first)
print('ret_last=',ret_last)
print('ret_1_10=',ret_1_10)

'''【结果】
>>  ret_exists= True
>>  ret_count= 99
>>  ret_first= User对象—> id=2,username=name1
>>  ret_last= User对象—> id=100,username=name99
>>  ret_1_10=  id=3,username=name2>,... ...  id=11,username=name10>]>
'''

3.3 查询条件

3.3.1 格式与关键字

【模型类中的字段名】__【条件关键字】=【比较值】

比较条件 关键字
判断相等 exact
模糊查询 包含:contains
开头:startswidth
结尾:endswith
是否为空 isnull
范围查询 in
比较运算 大于:gt
大于等于:gte
小于:lt
小于等于:lte
日期查询 年:year
月:month
日:day
小时:hour
分钟:minute
秒:second

3.3.2 判断相等 = 或 exact

# 没有被逻辑删除的User
user1_s = User.objects.filter(isdelete=0)
print(user1_s)
user2_s = User.objects.filter(isdelete__exact=0)
print(user2_s)

'''【结果】
>>   id=1,username=name0>,  id=3,username=name2>, ... ...
>>   id=1,username=name0>,  id=3,username=name2>, ... ...
'''

3.3.3 模糊查询 contains|startswith|endswith

# 查询用户名中包含'1'的用户
user1_s = User.objects.filter(username__contains='1')
print(user1_s)
# 查询用户名已以'name1'开头的用户
user2_s = User.objects.filter(username__startswith='name1')
print(user2_s)
# 查询邮箱以'@qq.com'结尾的用户
user3_s = User.objects.filter(email__endswith='@qq.com')
print(user2_s)

3.3.4 为空查询 isnull

# 查询生日为空的User对象
user_s = User.objects.filter(birthday__isnull=True)
print(user_s)

3.3.5 范围查询 in

# 查询username属于['name1','name2']的User对象
user_s = User.objects.filter(username__in=['name1','name2'])
print(user_s)

3.3.6 比较查询 gt gte lt lte

# 查询余额大于等于1000的User对象
user_s = User.objects.filter(money__gte=1000)
print(user_s)

3.3.7 日期查询 year month day hour minute second

# 查询生日中的'日'大于20号的User用户
user_s = User.objects.filter(birthday__day='20')
print(user_s)

3.3.8 字段比较 F

from django.db.models import F
# 查询在第一次创建后,发生修改的对象
user_s = User.objects.filter(updateDatetime__gt=F('createDatetime'))
print(user_s)

3.3.9 逻辑比较 Q

from django.db.models import Q
# 查询余额大于5000块的男性
print(User.objects.filter(money__gt=5000,gender=0))				# 第一种 逗号
print(User.objects.filter(Q(money__gt=5000) & Q(gender=0)))		# 第二种 Q(【条件】)&Q(【条件】)
# 查询余额大于5000块的男性和余额大于2000的女性
print(User.objects.filter(Q(money__gt=5000,gender=0)|Q(money__gt=2000,gender=1)))
# 得到上个查询结果的补集
print(User.objects.filter(~Q(money__gt=5000,gender=0)&~Q(money__gt=2000,gender=1)))

3.4 排序 order_by()

方法 说明
order_by(【字段1】,-【字段】) 先根据【字段1】升序排列,然后根据【字段2】降序排列
# 先根据createDatetime升序排列,对于createDatetime相同的数据,安装birthday降序排列
user_s = User.objects.all().order_by('createDatetime','-birthday')
print(user_s)

3.5 聚合aggregate()

关键字 说明
Sum 求和
Max 最大值
Min 最小值
Avg 平均值
Count 个数
from django.db.models import Avg

# 查询所有用户的余额平均值
money_all_avg = User.objects.aggregate(Avg('money'))
print(money_all_avg)
# 查询所有男用户的余额平均值
money_men_avg = User.objects.filter(gender=0).aggregate(Avg('money'))
print(money_men_avg)

'''【结果】
>>  {'money__avg': 3994.33}
>>  {'money__avg': 3938.66}
'''

4 增删改

4.1 save()

# 创建新的User
user = User(account='00101',username='name101',password='101')
user.save()
# 在save后 user会更新为数据库中存在的数据
print(user.id)
# 修改user
user.password = '102'
user.save()	# 把name101的密码改为102

说明:

  • 如果对象中的主键值不存在,save()方法相当于insert插入。
  • 如果对象中的主键值存在,save()方法相当于update修改。
  • save()方法会更新对象中的字段值(例如:刚创建user对象中没有id,在执行save()后,user对象得到了数据库中对应的id值)

4.2 create()

格式:【模型类名】.objects.create(字段名=字段值,… …)

user = User.objects.create(account='00102',username='name102',password='102')
print(user)

'''【结果】
>>  User对象—> id=102,username=name102
'''

4.3 update()

# 修改余额大于等于8000的用户的isdelete = 1,返回值是修改的行数
ret = User.objects.filter(money__gt=8000).update(isdelete=1)
print(ret)	

'''【结果】
>>  17
'''

4.4 delete()

# 物理删除
User.objects.filter(money__gt=10000).delete()

5 多表操作

5.1 外键种类

关键字 说明
ForeignKey 一对多 定义在多的一端中
ManyToManyField 多对多 定义在任意一方
OneToOneField 一对一 定义在任意一方

5.2 外键的常用参数

关键字 说明
to 引用的模型类
on_delete 外键约束
  on_delete=models.CASCADE 级联操作(多对一,一的一方删除,多的一方也删除)
  on_delete=models.PROTECT 报异常(被引用的一方不能删除)
  on_delete=models.SET_NULL 设置为null(多对一,一的一方删除,多的一方外键为null)
  on_delete=models.DO_NOTHING 什么也不做
related_name 反向引用,如果两个表间有多种外键关系,需要指明related_name

5.3 一对多

5.3.1 案例

models类:

from django.db import models

class User1(models.Model):
	name = models.CharField(max_length=16,unique=True)					# 用户名

class Forum1(models.Model):
	name = models.CharField(max_length=16,unique=True)					# 帖子主题
	# 发帖的用户
	userObject = models.ForeignKey(	    to=User1,					# ‘一’的一方的类
										on_delete=models.CASCADE	# 级联操作
									)								

一对多的数据维护与查询

# 添加用户
user = User1.objects.create(name='name1')

# 添加帖子,引用上面创建的用户
Forum1.objects.create(name='topic1',userObject=user)

# 得到用户发的所有帖子
#     一对多,【多的一方的class名小写_set】
forum_s = User1.objects.get(id=1).forum1_set.all()
print(forum_s)

# 得到帖子发送者对象
#     多对一,【通过定义的外键字段引用】
user = Forum1.objects.get(name='topic1').userObject
print(user)

'''【结果】
>	]>
>	User1 object
'''

5.3.2 引用关系

【Django知识点】模型层_第4张图片
1:M —>表示1对多
M得到引用的1:通过M中定义的外键字段,得到1
1得到被应用的所有M:通过M方的类名_set,返回时QuerySet对象,例如user1.forum1_set.all()

5.4 多对多(django维护中间表)

django会自动创建一个中间表:名称:【app名】【类名小写】【类名小写】

添加引用关系方法:add()
删除引用关系方法:remove()

class User2(models.Model):
	name = models.CharField(max_length=16,unique=True)	# 用户名
	def __str__(self):
		return str(self.name)
		
class Hobby2(models.Model):
	name = models.CharField(max_length=16,unique=True)	# 爱好名称
	userobjects = models.ManyToManyField(to=User2)		# 多对多
	
	def __str__(self):
		return str(self.name)
user1 = User2.objects.create(name='name1')
user2 = User2.objects.create(name='name2')
# 创建3个爱好对象
hobby1 = Hobby2.objects.create(name='早上写代码')
hobby2 = Hobby2.objects.create(name='中午写代码')
hobby3 = Hobby2.objects.create(name='晚上写代码')
# 通过用户,添加引用
user1.hobby2_set.add(hobby1)
user1.hobby2_set.add(hobby2)
# 通过爱好,添加引用
hobby3.userobjects.add(user1)
hobby3.userobjects.add(user2)

print(user1.hobby2_set.all())
print(hobby3.userobjects.all())

# hobby3删除引用的user1
hobby3.userobjects.remove(user1)
print(hobby3.userobjects.all())

'''【结果】
>>  , , ]>
>>  , ]>
>>  ]>
'''

5.5 多对多(自己维护中间表)

through指明中间表的模型类,如果自己指明了中间表,那么django就不会帮助维护了,所有的添加删除引用关系,都必须自己手动完成。

class User3(models.Model):
	name = models.CharField(max_length=16, unique=True)  # 用户名

	def __str__(self):
		return str(self.name)


class Hobby3(models.Model):
	name = models.CharField(max_length=16, unique=True)  # 爱好名称
	userobjects = models.ManyToManyField(to=User3,through='User3ToHobby3')  # 多对多

	def __str__(self):
		return str(self.name)

class User3ToHobby3(models.Model):
	user = models.ForeignKey(to=User3)
	hobby = models.ForeignKey(to=Hobby3)
# 创建用户对象
user1 = User3.objects.create(name='name1')
user2 = User3.objects.create(name='name2')
# 创建爱好对象
hobby1 = Hobby3.objects.create(name='早上写代码')
hobby2 = Hobby3.objects.create(name='中午写代码')
hobby3 = Hobby3.objects.create(name='晚上写代码')
# 自己手动维护中间表
User3ToHobby3.objects.create(user=user1,hobby=hobby1)
User3ToHobby3.objects.create(user=user1,hobby=hobby2)
User3ToHobby3.objects.create(user=user2,hobby=hobby2)
User3ToHobby3.objects.create(user=user2,hobby=hobby3)

print(user1.hobby3_set.all())
print(hobby3.userobjects.all())

'''【结果】
>>  , ]>
>>  ]>
'''

5.6 多对一自关联

to = ‘self’ 实现自关联
注意:

  • 推荐使用django来维护一对多的自关联模型
  • 多对多的自关联模型,推荐使用手动维护
class Area(models.Model):
	name = models.CharField(max_length=16,unique=True)		# 地区名字
	pArea = models.ForeignKey(to='self',null=True)		    # 上一级地区的引用

	def __str__(self):
		return str(self.name)
# area1:北京
area1 = Area.objects.create(name='北京')
# area2:朝阳
area2 = Area(name='朝阳')
# 设置area2的父地区是area1北京
area2.pArea = area1
area2.save()
# area3:丰台
area3 = Area.objects.create(name='丰台')
# area1北京的子地区,添加area3丰台
area1.area_set.add(area3)

area_beijing = Area.objects.get(name='北京')
area_chaoyang = Area.objects.get(name='朝阳')
area_fengtai = Area.objects.get(name='丰台')
# 打印北京的所有子区域
print(area_beijing.area_set.all())
# 打印朝阳的父区域
print(area_chaoyang.pArea)

'''【结果】
>>  , ]>
>>  北京
'''

5.7 多表查询


from django.db import models
from hashlib import md5
import datetime


class User(models.Model):
    account = models.CharField(max_length=16,unique=True)                 # 登录账号
    username = models.CharField(max_length=16,null=True,db_index=True)    # 用户昵称
    _password = models.CharField(max_length=32)                           # 密码,使用md5加密
    gender = models.IntegerField(default=0)                               # 性别,0:男,1:女
    birthday = models.DateField(null=True)                                # 生日
    money = models.DecimalField(max_digits=10,decimal_places=2,default=0) # 余额,总位数10,小数位2,默认0
    email = models.EmailField(null=True)                                  # 邮箱
    image = models.ImageField(null=True)                                  # 头像
    createDatetime = models.DateTimeField(auto_now_add=datetime.datetime.now())   # 创建时间
    updateDatetime = models.DateTimeField(auto_now=datetime.datetime.now())       # 最近一次修改时间
    isdelete = models.BooleanField(default=False)                         # 逻辑删除

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self,password):
        self._password = md5(password.encode('ascii')).hexdigest()

    def __str__(self):
        return str(self.username)

class Forum(models.Model):
    topic = models.CharField(max_length=100,unique=True)
    createDatetime = models.DateTimeField(auto_now_add=datetime.datetime.now())   # 创建时间
    updateDatetime = models.DateTimeField(auto_now=datetime.datetime.now())       # 最近一次修改时间

    sender = models.ForeignKey(to=User,on_delete=models.DO_NOTHING,related_name='sender_set')
    collectors = models.ManyToManyField(to=User,related_name='collectors_set')
    isdelete = models.BooleanField(default=False)                         # 逻辑删除


    def __str__(self):
        return str(self.topic)


def build_user(num = 100):
    for i in range(num):
        User.objects.create(
            account = '%05d' % i,
            username = 'name%s' % i,
            password = str(i),
            gender = i % 2,
            birthday = datetime.datetime.now() + datetime.timedelta(days=i),
            money = i ** 2 + 12.34 * i + 100,
            email = '%[email protected]' % i,
            createDatetime=datetime.datetime.now(),
            updateDatetime=datetime.datetime.now(),
            isdelete=i % 2,
        )


# ---------------这里重置一下数据库,重新执行一下build_user()----------------
# 根据id得到3个user对象
user1 = User.objects.get(id=1)
user2 = User.objects.get(id=2)
user3 = User.objects.get(id=3)
# 创建两个帖子forum对象
forum1 = Forum(topic='话题1')
forum2 = Forum(topic='话题2')
# forum1和forum2的发帖人都是user1
forum1.sender = user1
forum2.sender = user1
# 保存forum
forum1.save()
forum2.save()

# 用户2收藏帖子1
user2.collectors_set.add(forum1)
user2.save()
# 帖子1被用户3收藏
forum1.collectors.add(user3)
forum1.save()

print('查询id为1的用户发送的所有帖子', User.objects.get(id=1).sender_set.all())
print('查询id为1的帖子的所有收藏者',Forum.objects.get(id=1).collectors.all())

print('查询帖子,且发帖者的创建时间在2019-05-10之后', Forum.objects.filter(sender__createDatetime__gt='2019-05-10'))
print('查询用户,且用户的关注的帖子的topic中包含"1"', User.objects.filter(collectors_set__topic__contains='1'))

'''【结果】
>>  查询id为1的用户发送的所有帖子 , ]>
>>  查询id为1的帖子的所有收藏者 , ]>
>>  查询帖子,且发帖者的创建时间在2019-05-10之后 , ]>
>>  查询用户,且用户的关注的帖子的topic中包含"1" , ]>
'''

6 自定义管理器

# 定义一个Manager类,需要继承models.Manager
class MyManager(models.Manager):
	# 自定义一个方法,得到所有没有逻辑删除的数据
    def all_isnotdetele(self):
    	# 调用父类方法,传递参数
        return super().filter(isdelete=False)

class User4(models.Model):
	# 在模型类中实例化自己的管理器
    manager = MyManager()
    # 定义字段
    username = models.CharField(max_length=30)
    isdelete = models.BooleanField(default=False)
User4.manager.create(username='name1')
User4.manager.create(username='name2',isdelete=True)

print(User4.manager.all())
print(User4.manager.all_isnotdetele())

'''【结果】
>>  , ]>
>>  ]>
'''

objects其实是模型类的默认管理器
一个模型类中只能有一个管理器,如上,如果实例化manager = MyManager(),那么就不能使用User4.objects了,只能使用User4.manager。

也可以重写管理器的方法,例如:

class MyManager(models.Manager):
	# 重写管理的方法
    def all(self):
        return super().filter(isdelete=False)

你可能感兴趣的:(Django框架,django,查找,模型,多对多,manager)