对于django的model,尤其是related field,我建议从model的本身含义出发,而不要从数据库的角度去看。
related_field仅仅是表示model之间的关系,至于数据库的实现,需要的时候再去了解。这样才能比较容易的理解django的model设计思想。
比如ForeignKey的含义,就是多对一的关系。这里并非字段的对应,而是model的对应。也就是说,有多个model对应一个model。所以ForeignKey在django中,就是表示model的含义,而非字段。
ManyToManyField的含义,也是指定多个model对应于多个model的关系。
先建立所需的model:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
class
Color(models.Model):
name
=
models.CharField(max_length
=
10
)
def
__str__(
self
)
return
self
.name
class
Fruit(models.Model):
name
=
models.CharField(max_length
=
10
)
price
=
models.IntegerField()
color
=
models.ForeignKey(Color)
def
__str__(
self
)
return
self
.name
class
Area(models.Model):
province
=
models.CharField(max_length
=
10
)
fruits
=
models.ManyToManyField(Fruit)
def
__str__(
self
)
return
self
.name
class
User(models.Model):
name
=
models.CharField(max_length
=
10
)
fruits
=
models.ManyToManyField(Fruit, related_name
=
'related_name'
, related_query_name
=
'related_query_name'
)
def
__str__(
self
)
return
self
.name
|
Fruit与Area是多对多的关系, 一个地区会生产多种水果,而一种水果也会被多个地区生产。
Fruit与User是多对多的关系,一个用户可以喜欢多种水果,而一种水果也会被多个用户喜欢。
Fruit与Color是多对一,一种水果相对有一种颜色。
插入数据:
首先向Color插入数据:
|
1
2
3
4
5
6
|
>>> color_red
=
Color(name
=
'red'
)
>>> color_yellow
=
Color(name
=
'yellow'
)
>>> color_red.save()
>>> color_yellow.save()
>>> color_green
=
Color(name
=
'green'
)
>>> color_green.save()
|
然后向Fruit插入数据。注意color是Fruit的外键,所以添加时,需要指定color为Color的实例。
|
1
2
3
4
5
6
|
>>> apple
=
Fruit(name
=
'apple'
, price
=
10
, color
=
color_red)
>>> apple.save()
>>> orange
=
Fruit(name
=
'orange'
, price
=
5
, color
=
color_yellow)
>>> orange.save()
>>> watermelon
=
Fruit(name
=
'watermelon'
, price
=
20
, color
=
color_green)
>>> watermelon.save()
|
然后向Area添加数据。注意Area和Fruit是多对多的关系,必须先保存,然后在来指定两者的关系。
|
1
2
3
4
5
6
7
|
>>> shanghai
=
Area(province
=
'shanghai'
)
>>> shanghai.save()
>>> guangzhou
=
Area(province
=
'guangzhou'
)
>>> guangzhou.save()
>>> shanghai.fruits.add(apple)
>>> apple.area_set.add(guangzhou)
|
关系的添加和删除是由ManyRelatedManager对象管理的。
它的获取方式与ManyToManyField的定义的位置有关。
如果在有ManyToManyField的model中,直接提取字段名就可以。
在没有ManyToManyField的model中, 使用related_name获取,如果没有默认为xxx_set, xxx为对应的model名。
向User添加数据,
|
1
2
3
4
5
6
7
8
|
>>> jack
=
User(name
=
'jack'
)
>>> jack.save()
>>> jack.fruits.add(apple)
>>> orange.related_name.add(jack)
>>> july
=
User(name
=
'july'
)
>>> july.save()
>>> july.fruits.add(apple)
|
查询数据
查询有喜欢apple的user
|
1
2
|
>>> User.objects.
filter
(fruits__name
=
'apple'
)
<User: jack>, <User: july>]
|
这里使用了双下划线, xxxx1__xxxx2。
xxxx1的获取,
分为两种情况
-
ManyToManyField在model中
直接获取其字段名
-
ManyToManyField不在model中
a. 获取ManyToManyField的related_query_name属性。
b. 获取ManyToManyField的related_name属性。
c. 获取对应model名的小写格式。
xxxx2即为字段名。
查询有用户是jack的喜欢的水果
|
1
2
3
4
5
|
>>> Fruit.objects.
filter
(related_query_name__name
=
'jack'
)
[<Fruit: apple>, <Fruit: orange>]
>>>
>>> User.objects.get(name
=
'jack'
).fruits.
all
()
[<Fruit: apple>, <Fruit: orange>]
|
查询用户名是j开头的喜欢的水果
|
1
2
|
>>> Fruit.objects.
filter
(related_query_name__name__startswith
=
'j'
)
[<Fruit: apple>, <Fruit: orange>, <Fruit: apple>]
|
这里指定了related_name和related_query_name的属性值,比较特殊,是为了更好的解释其作用。
一般来说,我习惯把related_name设为model的名字加上s, related_query_name设为model的名。
比如上面的User中fruits字段,
|
1
|
fruits
=
models.ManyToManyField(Fruit, related_name
=
'users'
, related_query_name
=
'user'
)
|
最后有一点注意到,如果一个model会有两个指向同一个model的外键。那么这两个外键必须指定related_name,并且还不能相同。举例来说:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class
User(models.Model):
name
=
models.CharField(max_length
=
20
)
def
__str__(
self
):
return
self
.name
class
Message(models.Model):
content
=
models.CharField(max_length
=
200
)
sender
=
models.ForeignKey(User, related_name
=
'send_messages'
)
receiver
=
models.ForeignKey(User, related_name
=
'receive_messages'
)
def
__str__(
self
):
return
self
.content
|
写数据:
|
1
2
3
4
5
6
7
8
9
10
|
>>> names
=
[
'Mary'
,
'Jim'
,
'Sam'
]
>>>
for
name
in
names:
user
=
User(name
=
name)
user.save()
>>>
import
itertools
>>> users
=
User.objects.
all
()
>>>
for
sender, receiver
in
itertools.permutations(users,
2
):
content
=
'%s-to-%s'
%
(sender.name, receiver.name)
msg
=
Message(content
=
content, sender
=
sender, receiver
=
receiver)
msg.save()
|
在上面代码中,实例化三个人Mary,Jim,Sam。并且都互相发送了短信。
|
1
2
3
4
5
6
7
8
9
|
>>> Mary
=
User.objects.get(name
=
'Mary'
)
# get messages which Mary sends
>>> Mary.send_messages.
all
()
[<Message: Mary
-
to
-
Jim>, <Message: Mary
-
to
-
Sam>]
# get messages which Mary reveives
>>> Mary.receive_messages.
all
()
[<Message: Jim
-
to
-
Mary>, <Message: Sam
-
to
-
Mary>]
|
本文详细介绍了Django Model中几种特殊的关系字段,如ForeignKey、ManyToMany、OneToOne等,通过实例展示了如何创建和操作这些关系,以及如何查询和过滤相关数据。重点强调了从模型本身的含义出发理解字段的重要性,而不是仅仅从数据库角度考虑。
2910

被折叠的 条评论
为什么被折叠?



