好久没写了,这次用阴阳师来举例子。
Django Model的三种Relationship
- 一对一 (关键词 OneToOneField)
- 一对多 (关键词 ForeignKey) 没有OneToManyField这种写法
- 多对多 (关键词 ManyToManyField)
代码和关系
1 | from django.db import models |
- 式神和其cp为一对一关系,酒吞置于红叶,鲤鱼精至于河童。
- 稀有度和式神为一对多关系。 一个种稀有度能对应多个式神,但一个式神只能有一种稀有度。
- 御魂套和式神为多对多关系。一套御魂可以给多个式神使用,一个式神也可以使用多套御魂。
给数据库创建一些数据
创建的方法
- 使用对象属性来创建
- 使用objects来创建
使用对象属性创建
如果是创建自身的数据,则对象要调用save(),如果是创建关联性数据,则无需调用save()
1 | 创建了稀有度为n的数据 |
使用objects来创建
使用objects来创建无需调用save()
1 | >>> Rare.objects.create(level='sr') |
我该把关键词写在哪里
- OneToOneField,一对一的情况,随便写。
- ForeignKey,一对多的情况,写在多的一方,一种稀有度对应多个式神,所以ForeignKey定义在式神上,也就是class Formula上。
- ManyToManyField,多对多的情况,任意写。
- 建议将字段命名为关联class的小写,比如一对多,在class Formula需要定义一个ForeignKey字段和class Rare关联,则该字段名为’rare’。
1 | rare = models.ForeignKey(Rare, on_delete=models.CASCADE) |
三种关系的例子和相互读取
一对一
用酒吞和红叶举例子。
先创建酒吞,因为Formula有个rare字段的是关联了class Rare,所以要先获取rare的instance对象,将对象赋值给rare,然后创建酒吞。
这边要注意的是,如果获取instance对象,则需要用到get()方法,倘若使用的是filter(),则获取的是一个query set对象,是不能够给rare赋值的。
1 | ssr = Rare.objects.get(level='ssr') |
接着在Lover中创建红叶。formula是个传入的对象,所以先get()获取到酒吞
1 | >>> jiutun = Formula.objects.get(name='JiuTun') |
相互之间访问数据
- Formula到Lover
对象属性方式,formula对象直接访问lover的lover_name字段
1
2
3>>> jiutun = Formula.objects.get(name='JiuTun')
>>> jiutun.lover.lover_name
'HongYe'objects的方式,传入的formula是instance对象
1
2
3
4
5>>> jiutun = Formula.objects.get(name='JiuTun')
>>> Lover.objects.get(formula=jiutun)
<Lover: HongYe>
>>> Lover.objects.get(formula=jiutun).lover_name
'HongYe'
- Lover到Formula
- 对象属性方式,访问formula的name字段
1
2
3>>> hongye = Lover.objects.get(lover_name='HongYe')
>>> hongye.formula.name
'JiuTun' - objects的方式,传入的lover是instance对象
1
2
3
4>>> Formula.objects.get(lover=hongye)
<Formula: JiuTun>
>>> Formula.objects.get(lover=hongye).name
'JiuTun'一对多
通过对象属性的方式给给Formula添加鬼切式神。
1 | guiqie = Formula(name='GuiQie', rare=ssr) |
此时数据库内有数据了,formula为Guiqie,其rare为ssr。
相互之间访问数据
- 从多(Formula)到一(Rare)
对象属性方式
1
2
3>>> formula = Formula.objects.get(name='GuiQie')
>>> formula.rare.level
'ssr'objects方式,访问Rare的level字段
1
2
3
4>>> Rare.objects.get(formula=formula)
<Rare: ssr>
>>> Rare.objects.get(formula=formula).level
'ssr'
- 从一(Rare)到多(Formula)
因为访问多,所以属性方法访问要用_set,objects对象访问则建议用filter(),因为get()遇到大于1个数据会报错。
因为是访问的多,所以得到结果是query set类型,访问具体数据,需要迭代进行访问。
- 对象属性方式
1
2
3
4
5
6
7
8ssr = Rare.objects.get(level='ssr')
ssr.formula_set.all()
<QuerySet [<Formula: GuiQie>, <Formula: CiMuTongZi>]>
for i in ssr.formula_set.all():
print(i)
GuiQie
CiMuTongZi - objects方式
1
2
3
4
5
6
7ssr = Rare.objects.get(level='ssr')
formulas = Formula.objects.filter(rare=ssr)
for i in formulas:
print(i)
GuiQie
CiMuTongZi多对多
代码里,ManyToManyField定义在class Soul。
使用objects方式创建破势套和针女套
1 | >>> Soul.objects.create(set='PoShi') |
指定Soul(御魂)关联给Formula(式神),使用add的方式
1 | >>> zhennv = Soul.objects.get(set='ZhenNv') |
指定Formula(式神)关联给Soul(御魂),使用add的方式
1 | poshi = Soul.objects.get(set='PoShi') |
将指定御魂(Soul)关联所有式神(Formula),使用set()方法
1 | all = Formula.objects.all() |
将指定式神关联所有御魂,使用set()方法
1 | all = Soul.objects.all() |
相互之间访问数据(好像不存在objects访问的方法,待考证)
通过式神(Formula)获取御魂(Soul, ManyToManyField),使用_set.value()方式
对象属性方式
1
2>>> guiqie.soul_set.values()
<QuerySet [{'id': 1, 'set': 'ZhenNv'}]>
通过御魂(Soul, ManyToManyField)查询式神(Formula)
- 对象属性方式
1
2>>> poshi.formula.values()
<QuerySet [{'rare_id': 4, 'name': 'GuiQie'}]>
- 对象属性方式
refer
https://imliyan.com/blogs/article/Django%E6%95%B0%E6%8D%AE%E6%A8%A1%E5%9E%8B%E5%AE%9E%E4%BE%8B/
https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.OneToOneField
https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.ForeignKey
https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.ManyToManyField
https://docs.djangoproject.com/en/2.2/topics/db/examples/many_to_many/