Django:模型通过中间模型有两个多对多关系 [英] Django: model has two ManyToMany relations through intermediate model
问题描述
所以我是Django新手,想描述一下场景:有一堆Persons
,还有一堆Items
,一个人通过Items
给另一个 Person
.
So I am new to Django, and want to describe the scenario: there are a bunch of Persons
, and there are a bunch of Items
, and a person passes Items
to another Person
.
我有以下模型:
class Item(models.Model):
title = models.CharField(max_length=1024, blank=False)
def __unicode__(self):
return self.title
class Person(models.Model):
name = models.CharField(max_length=127, blank=False)
out_item = models.ManyToManyField(
Item,
through='Event',
through_fields=('from_user', 'item'),
related_name='giver'
)
in_item = models.ManyToManyField(
Item,
through='Event',
through_fields=('to_user', 'item'),
related_name='receiver'
)
def __unicode__(self):
return self.name
class Event(models.Model):
item = models.ForeignKey(Item)
from_user = models.ForeignKey(Person, related_name='event_as_giver')
to_user = models.ForeignKey(Person, related_name='event_as_receiver')
但是 makemigrations
告诉我 app.Person: (models.E003) 该模型通过中间模型 'app.Event' 有两个多对多关系.
不知道我做错了什么?或者什么是实现场景的干净方法?也许我可以将 Event
分成 GiveEvent
和 ReceiveEvent
?但这在直觉上意义不大,因为当传递 item 时实际上只有一个事件.
I wonder what I did wrong? Or what is a clean way to achieve the scenario? Perhaps I can separate Event
into GiveEvent
and ReceiveEvent
? But that just makes less sense intuitively, since there is actually only a single event when item is passed.
推荐答案
你所描述的听起来很合理.不允许这样做可能有技术原因;一个语义原因是每个ManyToManyField
都意味着创建一个新表,并且不能有两个同名的表(即由同一个类表示).
What you're describing sounds reasonable enough. There may be a technical reason why that's disallowed; one semantic reason is that each ManyToManyField
implies the creation of a new table, and there can't be two tables with the same name (i.e. represented by the same class).
另一种方法(更短更干)是这样的:
One alternative approach (shorter and more DRY) would be this:
class Person(models.Model):
name = models.CharField(max_length=127, blank=False)
to_users = models.ManyToManyField(
'self',
symmetrical=False,
related_name='from_users',
through='Event',
through_fields=('from_user', 'to_user'),
)
class Event(models.Model):
item = models.ForeignKey(Item, related_name='events')
from_user = models.ForeignKey(Person, related_name='events_as_giver')
to_user = models.ForeignKey(Person, related_name='events_as_receiver')
表结构相同但描述符不同.访问相关的 people 稍微容易一些,但是访问相关的 items 就有点困难(例如,而不是 person.out_items.all()
你会说 Item.objects.filter(events__from_user=person).distinct()
).
The table structure is the same but the descriptors are different. Accessing related people is a bit easier but accessing related items is a bit harder (for example, instead of person.out_items.all()
you would say Item.objects.filter(events__from_user=person).distinct()
).
这篇关于Django:模型通过中间模型有两个多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!