2012-02-08 9 views
12

Mam model, który posiada unikalną rodzajowego relacji klucza obcego:cofania unikalny rodzajowe klucza obcego (i powrocie do obiektu w przeciwieństwie do związanej Manager)

class Contact(models.Model): 
    ... 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = generic.GenericForeignKey() 

    class Meta: 
     unique_together = ('content_type', 'object_id',) 

ten sposób, że Contact może tylko kiedyś należeć do jeden obiekt. Zazwyczaj, gdy chcę, aby odwrócić relacje mogę zrobić

class Person(models.Model): 
    ... 
    contacts = generic.GenericRelation(Contact) 

i nazywając person.contacts.all() da mi wszystkie obiekty. Ponieważ tylko jeden Contact kiedykolwiek zostanie zwrócony w mojej sytuacji, czy istnieje lepszy sposób dostępu do tego obiektu w odwrotnej kolejności?

p.s. Mógłbym napisać person.contact.all()[0] ale musi być czystsze podejście

+0

Możliwy duplikat http: // stackoverflow .pl/questions/4893823/how-can-i-make-and-enforce-a-generic-onetoone-relationship-in-django –

+0

Wiem, że odpowiedź na moje pytanie jest (lub wydaje się być) w komentarzach, ale samo pytanie jest inne (dzięki za link - będę musiał teraz sprawdzić) –

+0

Stąd "możliwe";) –

Odpowiedz

12

Cóż, patrząc na pytanie w komentarzu Chrisa pomógł, a ja napisałem wstawek, aby powrócić do obiektu za pomocą szybkiego odnośnika (które powinny być buforowane):

class ContactMixin(object): 
    @property 
    def contactcard(self): 
     ctype = ContentType.objects.get_for_model(self.__class__) 
     try: 
      contact = Contact.objects.get(content_type__pk = ctype.id, object_id=self.id) 
     except Contact.DoesNotExist: 
      return None 
     return contact 

a osoba:

class Person(ContactMixin, models.Model): 
    ... 

teraz mogę po prostu zadzwonić

myperson.contactcard.phone_number 

nie zaakceptuje jeszcze, jak może istnieć inne propozycje

+2

ogólnie dobrą praktyką jest wskazanie wyjątków, których się spodziewasz (w tym przypadku nie ma on nic wspólnego i wieleobiektów zwróconych). W ten sposób przypadkowo nie ukryjesz innych wyjątków, które prawdopodobnie chcesz bulgotać – second

+0

Mam ten sam problem i patrząc na to rozwiązanie, nie sądzę, że 'select_related' ani' prefetch_related' działa na tym :(drogie naprawdę szybko, aby uzyskać właściwość 'contactcard' dla dużego zestawu zapytań. – user193130

5

jeśli queryset zawiera dokładnie jeden element można zrobić qs.get(), lub w przypadku

person.contact.get() 

(być może jeszcze trzeba złapać wyjątek DoesNotExists)

+1

Ciekawe, nie wiedziałem o tym. Unfortunatley 'person.contact' zwraca obiekt Managera/GenericRelation, więc nadal potrzebowałbym użyć' person.contacts.all.get', który jest równie kłopotliwy, –

Powiązane problemy