我正在建立词汇表,并具有以下模型:

class Word(Model):
 name = CharField(max_length=75)

class EnNoun(Model):
 word = OneToOneField(Word)

class FrNoun(Model):
 word = ForeignKey(Word)
 gender = CharField()
EnNounFrNoun中可以包含相同的单词。是否可以使用最少数量的查询(针对EnNounFrNoun的给定单词,针对给定单词提取结果(对于语言和词性,将有更多类似的类,例如ItAdverb)?

如何存储从一种语言到另一种语言的翻译(查询20个以上的表格不是一种选择)。
GenericForeign键有用吗?我一般如何使用它们?

我有以下翻译类:
@python_2_unicode_compatible
class Translation(Model):
    from_content_type = ForeignKey(ContentType, related_name='from_word_content_type')
    from_object_id = UUIDField(default=uuid.uuid4)
    from_word = GenericForeignKey('from_content_type', 'from_object_id')

    to_content_type = ForeignKey(ContentType, related_name='to_word_content_type')
    to_object_id = UUIDField(default=uuid.uuid4)
    to_word = GenericForeignKey('to_content_type', 'to_object_id')

但这不起作用:
Field 'to_word' does not generate an automatic reverse relation and therefore cannot be used for reverse querying. If it is a GenericForeignKey, consider adding a GenericRelation.

最佳答案

GenericForeignKey尝试为您提供ForeignKey行为,但是却针对一种对象类型,而是针对一组对象类型执行此操作(这就是为什么要用2列定义它们的原因,其中1列保留primary_key,另一列保留contenty_type)。
GenericRelationGenericForeignKey的反向关系,因为Django不会自动为GenericForeignKeys创建反向关系(与ForeignKeys不同),您必须手动设置它们。

我对翻译/词汇人员的最佳做法不是很熟悉,但是如果您想使用GenericRelationsGenericForeignKeys解决问题,一种解决方法是:

class Word(Model):
    name = CharField(max_length=75)
    nouns = GenericRelation('WordNoun', content_type_field='noun_ct', object_id_field='noun_id')

class WordNoun(Model):
    word = ForeignKey(Word)
    noun_ct = ForeignKey(ContentType,
        on_delete=models.CASCADE,
        #this is optional
        limit_choices_to = {"model__in": ('EnNoun', 'FrNoun')}
    )
    noun_id = PositiveIntegerField()
    noun = GenericForeignKey('noun_ct', 'noun_id')

class EnNoun(Model):
    word = OneToOneField(Word)

class FrNoun(Model):
    word = ForeignKey(Word)
    gender = CharField()

我们基本上是在建立一个模型来保持单词-名词关系,
这给以下
# Having some word
word = Word.objects.get(pk=1)

# With 1 query you can get a list with
# all WordNoun objects for this word.
word_nouns = word.nouns.all()

这种方法的问题在于,您获得了word_nouns列表后,
访问单个noun实例将进行新查询。
for word_noun in word.nouns.all():
    print word_noun.noun #this will make a query

一种略微优化此方法的方法是使用prefetch_related,因此,如果单个word具有3 word_nouns(假设1 EnNoun和2 FrNoun)。

然后,我们将其优化为3个查询-3个查询-1个word_nouns和2个每个noun(word_nounscontenty_type),而不是4个查询-EnNoun 1个,每个FrNoun 3个。
for word_noun in word.nouns.all().prefetch_related('noun'):
    print word_noun.noun #this will not make a query

区别在于查询的数量现在将取决于不同ContentTypes的数量,而不是相关的WordNoun对象的数量。

当您要预取的列表中的一个Nouns中有多个contenty_type时,此缩放比例很好,但是如果您有1个Noun per contenty_type`,则没有什么区别。

我可以想到的另一种方法是使用以下模型结构:
class Word(Model):
    name = CharField(max_length=75)

class WordNoun(Model):
    LANG_CHOICES = (
        ('en', 'English'),
        ('fr', 'French'),
    )
    word = ForeignKey(Word)
    lang = models.CharField(max_length=2, choices=LANG_CHOICES)
    gender = CharField(max_length=2, blank=True, default='')


#Now accessing all word_nouns would as easy as:
word_nouns = word.wordnoun_set.all()

10-06 08:40