Generic one-to-one relation in Django Generic one-to-one relation in Django django django

Generic one-to-one relation in Django


I recently came across this problem. What you have done is fine, but you can generalise it a little bit more by creating a mixin that reverses the relationship transparently:

class Event(models.Model):    content_type      = models.ForeignKey(ContentType)    object_id         = models.PositiveIntegerField()    content_object    = generic.GenericForeignKey('content_type', 'object_id')    class Meta:        unique_together   = ('content_type', 'object_id')class EventMixin(object):     @property     def get_event(self):         ctype = ContentType.objects.get_for_model(self.__class__)         try:             event = Event.objects.get(content_type__pk = ctype.id, object_id=self.id)         except:            return None          return eventclass Action1(EventMixin, models.Model):    # Don't need to mess up the models fields (make sure the mixing it placed before models.Model)    ...

and

action = Action1.object.get(id=1)event = action.get_event

You might want to add caching to the reverse relationship too


Use .get() return raise if object doesn't exist, .first() return None if object doesn't exist.

Name events_relation is an elegant way to differentiate event from events.

class Event(models.Model):    content_type      = models.ForeignKey(ContentType)    object_id         = models.PositiveIntegerField()    content_object    = generic.GenericForeignKey('content_type', 'object_id')    class Meta:        unique_together   = ('content_type', 'object_id') # Importantclass Action1(models.Model):    events_relation = generic.GenericRelation(Event)    @property    def event(self):        # Return the object in exists        # else None         return self.events_relation.first()