2011-10-20 13 views
18

Necesito configurar una relación uno a uno que también debe ser genérica. Puede ser que me puedas aconsejar un mejor diseño. Hasta el momento se me ocurrió a los siguientes modelosRelación uno-a-uno genérica en Django

class Event(models.Model): 
    # skip event related fields... 
    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 Action1(models.Model): 
    # skip action1 related fields... 
    events = generic.GenericRelation(Event, content_type_field='content_type', object_id_field='object_id') 

    @property 
    def event(self): 
     return self.events.get() # <<<<<< Is this reasonable? 

class Action2(models.Model):... 

En Django administración en la lista de eventos que desea recoger todas las acciones, y desde allí quiero ir a la página de administración para las acciones. ¿Es posible evitar la creación de la propiedad event en los modelos de acción? ¿Hay una mejor solución? Sería bueno combinar el campo events y la propiedad event en una sola definición. El proyecto con el que estoy trabajando usa Django 1.1

+0

Si realmente desea evitar 'events', deberá implementar la consulta manualmente en la tabla' Event', como se sugiere a continuación. Todavía preferiría tener 'events' como GenericRelation y luego usar' self.events.first() 'en la propiedad' event'. Además, esto le permitiría eliminar más fácilmente la restricción única en el futuro. – alexcasalboni

Respuesta

14

Hace poco came across this problem. Lo que han hecho está muy bien, pero se puede generalizar un poco más por la creación de un mixin que invierte la relación transparente:

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 event 

class Action1(EventMixin, models.Model): 
    # Don't need to mess up the models fields (make sure the mixing it placed before models.Model) 
    ... 

y

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

Es posible que desee agregar el almacenamiento en caché a la inversa relación también

+0

Funciona bien, pero no es capaz de hacer: 'Action.objects.select_related ('event')' – ramusus

+0

No me gusta esta solución -> una 'GenericRelation' se ve mucho mejor, incluso si necesita usar 'self.events.get()' o 'self.events.first()' – alexcasalboni

+0

Igual que los comentarios anteriores. Lo que originalmente tenías con 'GenericRelation' es mucho mejor. –

Cuestiones relacionadas