2010-09-13 16 views
5

Aparte de un ejemplo en los documentos, no encuentro ninguna documentación sobre cómo exactamente elige django el nombre con el que se puede acceder al objeto hijo desde el objeto principal. En su ejemplo, que hacen lo siguiente:¿Cómo se relacionan las relaciones de uno a uno de django con el nombre del objeto secundario?

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 

Así que en su ejemplo, que simplemente llaman p1.restaurant sin definir explícitamente ese nombre. Django supone que el nombre comienza con minúsculas. ¿Qué sucede si el nombre del objeto tiene más de una palabra, como FancyRestaurant?

Nota al margen: Estoy tratando de extender el objeto Usuario de esta manera. ¿Podría ser ese el problema?

Respuesta

11

Si define un related_name personalizado, lo usará, de lo contrario minará el nombre completo del modelo (en su ejemplo .fancyrestaurant). Ver el bloque más en 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()) 

Y así es como el OneToOneField calls it:

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

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

El opts.object_name (referencia en el django.db.models.related.get_accessor_name) defaults to cls.__name__.

En cuanto a

Nota al margen: Estoy tratando de ampliar el objeto usuario de esta manera. ¿Podría ser el problema?

No, no lo hará, el modelo User es solo un modelo regular de django. Solo ten cuidado con las colisiones related_name.

Cuestiones relacionadas