2011-10-20 11 views
18

Ho bisogno di impostare una relazione uno a uno che deve essere anche generica. Potrebbe essere tu puoi consigliarmi un design migliore. Finora mi è venuta ai seguenti modelliRelazione uno-a-uno generica in 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):... 

In Django Admin nella lista degli eventi che voglio raccogliere tutte le azioni, e da lì che voglio andare a pagine di amministrazione per le azioni. È possibile evitare di creare la proprietà event nei modelli di azione? C'è una soluzione migliore? Sarebbe bello combinare il campo events e la proprietà event in un'unica definizione. Il progetto con cui sto lavorando utilizza Django 1.1

+0

Se si vuole veramente evitare 'eventi', è necessario implementare manualmente la query sulla tabella' Evento', come suggerito di seguito. Preferirei comunque avere 'events' come una GenericRelation e quindi usare' self.events.first() 'nella proprietà' event'. Inoltre, ciò consentirebbe più facilmente di rimuovere il vincolo univoco, in futuro. – alexcasalboni

risposta

14

Ho recentemente came across this problem. Quello che hai fatto va bene, ma si può generalizzare un po 'di più con la creazione di un mixin che inverte il rapporto in modo trasparente:

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) 
    ... 

e

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

si potrebbe desiderare di aggiungere il caching sul retro rapporto anche

+0

Funziona bene, ma non dà la possibilità di fare: 'Action.objects.select_related ('event')' – ramusus

+0

Non mi piace questa soluzione -> un 'GenericRelation' sembra molto meglio, anche se è necessario utilizzare 'self.events.get()' o 'self.events.first()' – alexcasalboni

+0

Come i commenti sopra. Quello che avevi in ​​origine con 'GenericRelation' è molto meglio. –

Problemi correlati