您的位置:首页 > 编程语言 > Go语言

django.relatedField-关联域

2015-01-22 00:00 274 查看
摘要: 在django的model中,有几个特殊的field,来表示model之间的关系。比如ForeignKey,ManyToMany,OnetoOne

对于django的model,尤其是related field,我建议从model的本身含义出发,而不要从数据库的角度去看。

related_field仅仅是表示model之间的关系,至于数据库的实现,需要的时候再去了解。这样才能比较容易的理解django的model设计思想。

比如ForeignKey的含义,就是多对一的关系。这里并非字段的对应,而是model的对应。也就是说,有多个model对应一个model。所以ForeignKey在django中,就是表示model的含义,而非字段。

ManyToManyField的含义,也是指定多个model对应于多个model的关系。

先建立所需的model:

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插入数据:

>>> 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的实例。

>>> 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是多对多的关系,必须先保存,然后在来指定两者的关系。

>>> 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添加数据,

>>> 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

>>> 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的喜欢的水果
>>> Fruit.objects.filter(related_query_name__name='jack')
[<Fruit: apple>, <Fruit: orange>]
>>>
>>> User.objects.get(name='jack').fruits.all()
[<Fruit: apple>, <Fruit: orange>]


查询用户名是j开头的喜欢的水果
>>> 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字段,

fruits = models.ManyToManyField(Fruit, related_name='users', related_query_name='user')


最后有一点注意到,如果一个model会有两个指向同一个model的外键。那么这两个外键必须指定related_name,并且还不能相同。举例来说:

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

写数据:

>>> 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。并且都互相发送了短信。

>>> 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>]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: