Understanding Django GenericForeignKey and GenericRelation

后端 未结 2 1880
鱼传尺愫
鱼传尺愫 2020-12-14 12:34

I\'m building vocabulary and have following models:

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

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

cl         


        
2条回答
  •  情话喂你
    2020-12-14 13:32

    It is possible to add several GenericForeignKey to the same model. This would allow you to create a "link" between objects with generic type. I give an example latter. I modified your example to create something more useful in my sense. The table Translation create links between French and English words. Words are stored in classes EnVerb, FrVerb, EnNoun and FrNoun. Without GenericForeignKey, you would have to create two translation models: TranslationVerb and TranslationNoun. But in the following code, I show a generic translation model working for both verbs, and nouns. I hope it makes sense!

    More technically, you forgot to add the GenericRelation field. Also, they must specify the new names of the fields content_type and object_id in the GenericRelation field of the related objects.

    EXAMPLE

    from django.db import models
    from django.contrib.contenttypes.fields import GenericRelation
    from django.contrib.contenttypes.fields import GenericForeignKey
    from django.contrib.contenttypes.models import ContentType
    
    Translation(models.Model):
        fr_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, related_name="fr_content_type")
        fr_object_id = models.PositiveIntegerField()
        fr_word = GenericForeignKey('fr_content_type', 'fr_object_id')
    
        en_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, related_name="en_content_type")
        en_object_id = models.PositiveIntegerField()
        en_word = GenericForeignKey('en_content_type', 'en_object_id')
    
    class FrVerb(models.Model):
        name = models.CharField(max_length=75)
        translation = GenericRelation(Translation, content_type_field='fr_content_type', object_id_field='fr_object_id')
    
    class FrNoun(models.Model):
        name = models.CharField(max_length=75)
        gender = models.CharField(max_length=75)
        translation = GenericRelation(Translation, content_type_field='fr_content_type', object_id_field='fr_object_id')
    
    class EnVerb(models.Model):
        name = models.CharField(max_length=75)
        translation = GenericRelation(Translation, content_type_field='en_content_type', object_id_field='en_object_id')
    
    class EnNoun(models.Model):
        name = models.CharField(max_length=75)
        translation = GenericRelation(Translation, content_type_field='en_content_type', object_id_field='en_object_id')
    

    You can use this to create generic translations between models :

    from polls.models import *      
    
    EnNoun(name='tree').save()                                                                                                                       
    FrNoun(name='arbre').save()                                                                                                                      
    EnVerb(name='be').save()                                                                                                                         
    FrVerb(name='etre').save()                                                                                                                       
    
    trans1 = Translation(fr_word=FrNoun.objects.first(), en_word=EnNoun.objects.first())                                                              
    trans2 = Translation(fr_word=FrVerb.objects.first(), en_word=EnVerb.objects.first())
    

    Now trans1 is used to link 'tree' and 'arbre' and trans2 to link 'be' et 'être' while these objects belongs to different models !

提交回复
热议问题