2010-09-13 9 views
5

Bis auf ein Beispiel in der Dokumentation kann ich keine Dokumentation darüber finden, wie genau Django den Namen auswählt, mit dem man vom übergeordneten Objekt auf das Kindobjekt zugreifen kann. In ihrem Beispiel, sie wie folgt vor:Wie ordnen Django-Eins-zu-Eins-Beziehungen den Namen dem untergeordneten Objekt zu?

class Place(models.Model): 
     name = models.CharField(max_length=50) 
     address = models.CharField(max_length=80) 

     def __unicode__(self): 
      return u"%s the place" % self.name 

    class Restaurant(models.Model): 
     place = models.OneToOneField(Place, primary_key=True) 
     serves_hot_dogs = models.BooleanField() 
     serves_pizza = models.BooleanField() 

     def __unicode__(self): 
      return u"%s the restaurant" % self.place.name 

    # Create a couple of Places. 
    >>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton') 
    >>> p1.save() 
    >>> p2 = Place(name='Ace Hardware', address='1013 N. Ashland') 
    >>> p2.save() 

    # Create a Restaurant. Pass the ID of the "parent" object as this object's ID. 
    >>> r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False) 
    >>> r.save() 

    # A Restaurant can access its place. 
    >>> r.place 
    <Place: Demon Dogs the place> 
    # A Place can access its restaurant, if available. 
    >>> p1.restaurant 

So in ihrem Beispiel, sie einfach p1.restaurant aufrufen, ohne diesen Namen explizit zu definieren. Django nimmt an, dass der Name mit Kleinbuchstaben beginnt. Was passiert, wenn der Objektname mehr als ein Wort hat, wie zB FancyRestaurant?

Seitennotiz: Ich versuche, das Benutzerobjekt auf diese Weise zu erweitern. Könnte das das Problem sein?

Antwort

11

Wenn Sie eine benutzerdefinierte related_name definieren, wird diese verwendet, andernfalls wird der gesamte Modellname (in Ihrem Beispiel) kleingeschrieben. Siehe den anderen Block in django.db.models.related code:

def get_accessor_name(self): 
    # This method encapsulates the logic that decides what name to give an 
    # accessor descriptor that retrieves related many-to-one or 
    # many-to-many objects. It uses the lower-cased object_name + "_set", 
    # but this can be overridden with the "related_name" option. 
    if self.field.rel.multiple: 
     # If this is a symmetrical m2m relation on self, there is no reverse accessor. 
     if getattr(self.field.rel, 'symmetrical', False) and self.model == self.parent_model: 
      return None 
     return self.field.rel.related_name or (self.opts.object_name.lower() + '_set') 
    else: 
     return self.field.rel.related_name or (self.opts.object_name.lower()) 

Und hier ist, wie die OneToOneField calls it:

class OneToOneField(ForeignKey): 
    ... snip ... 

    def contribute_to_related_class(self, cls, related): 
     setattr(cls, related.get_accessor_name(), 
       SingleRelatedObjectDescriptor(related)) 

Die opts.object_name (im django.db.models.related.get_accessor_name verwiesen) defaults to cls.__name__.

Was

Randbemerkung: Ich versuche, das User-Objekt auf diese Weise zu erweitern. Könnte das das Problem sein?

Nein, es ist nicht, das User Modell ist nur ein normales Django-Modell. Achten Sie nur auf related_name Kollisionen.