And*_*unt 4 django django-models
我正在建立词汇表,并具有以下模型:
class Word(Model):
name = CharField(max_length=75)
class EnNoun(Model):
word = OneToOneField(Word)
class FrNoun(Model):
word = ForeignKey(Word)
gender = CharField()
Run Code Online (Sandbox Code Playgroud)
EnNoun和中可以有相同的单词FrNoun。是否可以使用最少数量的查询(和语言和词性类似的类更多,例如)来为EnNoun和两者获取给定单词的结果?FrNounItAdverb
如何存储从一种语言到另一种语言的翻译(查询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')
Run Code Online (Sandbox Code Playgroud)
但是它不起作用:字段“ to_word”不会生成自动反向关系,因此不能用于反向查询。如果它是GenericForeignKey,请考虑添加GenericRelation。
GenericForeignKey尝试给你一个ForeignKey行为,而是要针对一个类型的对象,他们是为了一组对象类型的(这就是为什么它们与2列,1保持定义primary_key,另一个保留contenty_type)。
GenericRelation是的反向关系GenericForeignKey,因为Django不会自动为您创建反向关系GenericForeignKeys(不同于ForeignKeys),您必须手动设置它们。
我对翻译/词汇人员的最佳做法不是很熟悉,但是如果您想使用GenericRelations和解决问题GenericForeignKeys,一种解决方法是:
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()
Run Code Online (Sandbox Code Playgroud)
我们基本上是在建立一个保持单词-名词关系的模型,这给出了以下内容
# 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()
Run Code Online (Sandbox Code Playgroud)
这种方法的问题在于,获取word_nouns列表后,访问单个noun实例将进行新查询。
for word_noun in word.nouns.all():
print word_noun.noun #this will make a query
Run Code Online (Sandbox Code Playgroud)
一种稍微优化此方法的方法是使用prefetch_related,因此,如果一个word具有3个word_nouns(让我们说1 EnNoun和2 FrNoun)。
然后,而不是4项的查询- 1为word_nouns和3对每个noun,我们把它优化至3项的查询- 1为word_nouns和2的每个contenty_type(EnNoun和FrNoun)
for word_noun in word.nouns.all().prefetch_related('noun'):
print word_noun.noun #this will not make a query
Run Code Online (Sandbox Code Playgroud)
区别在于查询的数量现在将取决于不同的数量ContentTypes,而不是相关WordNoun对象的数量。
这种秤不错,当你有几个Nouns从一个contenty_type在你预取列表中,但将没有什么区别,如果你有1个Noun percontenty_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()
Run Code Online (Sandbox Code Playgroud)