管理员在django中内联编辑多对多关系

时间:2012-06-19 19:51:19

标签: django django-models django-admin

我在Django中开发的模型有点复杂。基本的想法是网站上的用户可以给人们奖励,但我也想跟踪用户和奖励收件人之间的关系。用户可以给同一个人多个奖励,但他们之间只有一个关系。模型看起来像这样(用户是标准的auth_user模型):

class Recipient(models.Model):
    name = models.CharField(max_length=255)
    senders = models.ManyToManyField(User, through='Relationship')

class Relationship(models.Model):
    user = models.ForeignKey(User)
    recipient = models.ForeignKey(Recipient)
    relationship = models.CharField(max_length=255, blank=True, default='')
    class Meta:
        unique_together = (('user', 'recipient'),)

class Award(models.Model):
    recipient = models.ForeignKey(Recipient)
    user = models.ForeignKey(User)
    relationship = models.ForeignKey(Relationship)
    award_name = models.CharField(max_length=255)

在管理员中我有类似

的内容
class RelationshipInline(admin.StackedInline):
    model = Relationship

class AwardAdmin(admin.ModelAdmin):
    inlines = [RelationshipInline]
    exclude = ['relationship']

admin.site.register(Recipient)
admin.site.register(Award, AwardAdmin)

当我尝试在管理员中添加奖励时,我会收到错误“< class'Adisgence'>没有ForeignKey到< class'Accept'>”。我意识到这是因为当我编辑Award时,Django不知道应该内联编辑哪个关系,但事实上(对人类而言)它是具有相同用户/收件人对的那个。我不能指定Relationship中的用户/收件人是一个键,因为Django不支持多列键(所以我所能做的就是将它们指定为unique_together)。同样,我无法指定Award中的用户/收件人是关系的多列外键。

有没有办法得到我想要的东西?当与奖励中的多对一关系时,必须在管理员中单独编辑关系似乎是一个巨大的不便。有没有更好的方法来组织模型?

1 个答案:

答案 0 :(得分:1)

导致您所描述的错误的基本问题是因为您无法在“奖励”中使用“关系”内联,因此它应该是正常工作的另一种方式。这是有道理的,因为内联旨在提供一种创建绑定到您正在编辑的父记录(奖励)的任意数量的相关记录(在本例中为关系)的方法,但奖励只能与一个关系相关,因此使用内联不起作用。

无论如何,我会建议一些简化......

我建议完全放弃Recipient模型并切换到类似的东西:

class Relationship(models.Model):
    user1 = models.ForeignKey(User)
    user2 = models.ForeignKey(User)
    relationship = models.CharField(max_length=255, blank=True, default='')
    class Meta:
        unique_together = (('user1', 'user2'),)

class Award(models.Model):
    recipient = models.ForeignKey(User)
    user = models.ForeignKey(User)
    relationship = models.ForeignKey(Relationship)
    award_name = models.CharField(max_length=255)

而且,我不会专门管理Award模型中的'relationship'值,而是覆盖save()方法来获取或创建2个用户的关系并保存。这看起来像这样(未经测试):

...
from django.db.models import Q
...
class Award(models.Model):
    ...
    def save(self, *args, **kwargs):
        try:
            # Query for an existing relationship between the 2 users in question...
            relationship = Relationship.objects.get(
                (Q(user1=self.recipient) & Q(user2=self.user)) | (Q(user1=self.user) & Q(user2=self.recipient))
            )
        except:
            relationship = Relationship.objects.create(user1=self.recipient, user2=self.user, relationship='Pals')
        self.relationship = relationship
        super(Award, self).save(*args, **kwargs)