1

私が Django で開発しているモデルには、やや複雑な状況があります。基本的な考え方は、サイトのユーザーが人に賞を与えることができるというものですが、ユーザーと受賞者の関係も追跡したいと考えています。ユーザーは同じ人に複数の賞を与えることができますが、それらの間には 1 つの関係しかありません。モデルは次のようになります (ユーザーは標準の 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 'Relationship'> には <class 'Award'> への ForeignKey がありません」というエラーが表示されます。これは、Award を編集するときに、Django がどの関係をインラインで編集する必要があるかを認識していないためだと認識していますが、実際には (人間にとって) 同じユーザー/受信者のペアを持つものであることは明らかです。Django は複数列のキーをサポートしていないため、Relationship のユーザー/受信者がキーであることを指定できません (そのため、できることはそれらを unique_together として指定することだけです)。同様に、Award のユーザー/受信者が Relationship への複数列の外部キーであることを指定することはできません。

ここで取得しようとしているものを取得する方法はありますか? Award から多対 1 の関係がある場合、管理者で関係を個別に編集しなければならないのは非常に不便です。モデルを整理するためのより良い方法はありますか?

4

1 に答える 1

1

あなたが説明したエラーの原因となる基本的な問題は、「賞」で「関係」をインライン化できないためです。正しく機能するには、逆にする必要があります。インラインは、編集中の親レコード (賞) にバインドされた任意の数の関連レコード (この場合は関係) を作成する手段を提供するためのものですが、賞は 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 モデルの「関係」値を具体的に管理するのではなく、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)
于 2012-06-19T21:23:06.877 に答える