モデルとその関係を設計する上で、助けが必要になる可能性があります。
簡単な概要
- 本:本のタイトル(例:「Lordof theRings」)
- タグ:本に関連するタグ(例:「ファンタジー」、「ウィザード」、「エピックファイト」)
- アスペクト:タグに関連付けられたアスペクト、つまり、特定のタグが発生したときにユーザーが評価できるもの。例:
- タグの「ファンタジー」の側面は「世界の詳細」と「時間」である可能性があります
- タグの「エピックファイト」の側面は「ゴアレベル」と「ファイトテンション」である可能性があります
各タグは、Bookの複数のインスタンスで使用できます(たとえば、「指輪物語」と「ディスクワールド」の両方に「ファンタジー」というタグが付いています)。
各アスペクトは、タグの複数のインスタンスで使用できます(たとえば、「ファンタジー」と「サイエンスフィクション」の両方に「ワールドディテール」のアスペクトがあります)。
説明的な画像は次のとおりです。
(うわー、これらは大きなものです)
「なぜその追加のテーブルBookAspectが必要なのですか?」あなたは尋ねるかもしれませんか?
特定の本に関連する各側面のユーザー評価を保存したいからです。
それがここでの主な問題です。これをDjangoでモデル化したいのですが、これは私がこれまでに得たものです。
class Book(models.Model):
title = models.CharField(max_length=100, unique=True)
tags = ManyToManyField(Tag)
# the following line is a workaround...
aspects = models.ManyToManyField(Aspect, through='BookAspect')
class Tag(models.Model):
name = models.CharField(max_length=100)
aspects = models.ManyToManyField(Aspect)
class Aspect(models.Model):
name = models.CharField(max_length=100)
# this class is a workaround ...
class BookAspect(models.Model):
book = models.ForeignKey(Book)
aspect = models.ForeignKey(Aspect)
# this is from django-ratings
rating = RatingField(range=5, can_change_vote=True, allow_delete=True, blank=True)
class Meta:
unique_together = ('book', 'aspect',)
モデルに加えて、私は次のm2m_changed
シグナルリスナーを作成しましたaction="post_add"
:
@receiver(m2m_changed, sender=Book.tags.through)
def m2m_changed_book(sender, instance, action, reverse, pk_set, **kwargs):
if action is not 'post_add' or reverse:
return
# iterate through all newly created tags to manually add
# the aspects from each tag to the BookAspect table
for tag_id in pk_set:
aspects = Tag.objects.get(pk=tag_id).aspects.all()
# this is annoying, i have to manually set the relations...
for aspect in aspects:
bookAspect = BookAspect(book=instance, aspect=aspect)
bookAspect.save()
それは機能するはずですが、削除されたタグを処理するために追加のロジックが必要になります。
しかし、本当に厄介なのは、ユーザーの評価を保存できるように、本ごとのアスペクト関係を手動で追加する必要があることです。当然、私は異なる本の同じ側面に対して異なる評価が必要です。