2009-04-28 19 views
5

que tienen algo como esto en models.py¿Importa el orden de la declaración en models.py (Django/Python)?

class ZipCode(models.Model): 
    zip = models.CharField(max_length=20) 
    cities = City.objects.filter(zip=self).distinct() 

class City(models.Model): 
    name = models.CharField(max_length=50) 
    slug = models.CharField(max_length=50) 
    state = models.ForeignKey(State) 
    zip = models.ManyToManyField(ZipCode) 

Cuando hago esto me sale:

NameError: name 'City' is not defined 

Es esto porque el orden de los asuntos de declaración? Y si es así, ¿cómo puedo hacer esto? Porque de cualquier forma que lo organice, parece que obtendré un NameError.

Gracias.

Respuesta

2

Sí, el orden sí importa, como han notado otros.

Aunque, encontrar este problema casi siempre será una indicación de que estás haciendo algo mal.

En este caso, su declaración:

cities = City.objects.filter(zip=self).distinct() 

... es a la vez redundant y malas prácticas. Puede encontrar las ciudades relacionadas con un código postal haciendo referencia al city_set de ese código postal en sus vistas (es decir, ¡no en su modelo!). Así que si zip es una instancia de Código Postal, que haría:

cities = zip.city_set.all() 

Si realmente quieren llamarlo 'ciudades' en lugar de '' city_set puede utilizar el parámetro related_name en su declaración de M2M.

0

El orden importa en Python. This thread puede ser relevante para su pregunta. También para su uso, es posible que desee utilizar una clave externa única en la clase de código postal.

2

Sí, el orden sí importa, pero su ejemplo no me parece correcto. Creo que sólo debe utilizar una clave externa para su relación muchos-a-uno:

cities = models.ForeignKey(City) 

This has the details en las relaciones muchos-a-uno con modelos de Django.

Editar:

Se señaló a mí en los comentarios que las ciudades de Europa puede tener varias ciudades en el mismo código postal. Si está buscando una relación de muchos a muchos aquí, se debe utilizar:

cities = models.ManyToManyField(City) 

Esto se describe en Django's documentation. El punto es que este es cualquiera de estos ejemplos que son mucho más claros que los que se usan en el ejemplo.

+1

Hola Shane, tu sugerencia parece implicar que un código postal puede estar asociado con una sola ciudad, pero pensé que los códigos postales pueden pertenecer a más de una ciudad y una ciudad puede tener múltiples códigos postales. ¿No es ese el caso? – rick

+0

No, puede tener relaciones de muchos a uno, pero no estoy familiarizado con la sintaxis que ha utilizado aquí. De acuerdo con el enlace que proporcioné arriba: "Para definir una relación muchos a uno, use ForeignKey()" –

+0

Muchos a uno y muchos a muchos son dos relaciones diferentes, Shane. En este caso, de muchos a muchos probablemente sea más apropiado como un código postal único que puede representar varias ciudades (pensando internacionalmente). Eso es además del punto sin embargo. Declarar una relación binaria en ambas direcciones es a la vez una mala idea y redundante. – ozan

5

Cuando se tiene referencias a clases definidas después, puede utilizar este truco:

attribute = models.ForeignKey('ClassDefinedAfterThis') 
+0

¿Esto funcionaría sin embargo? cities = 'City'.objects.filter (zip = self) .distinct() – rick

+0

Su posición no debería importar en ese punto – phillc

+2

@rick: No, eso no funcionará. –

3

vez fui preocupado por orden ... porque pensé que mis modelos abajo sólo podía modelos de referencia más arriba. Pero luego se dio cuenta de que puede hacer un

models.ForeignKey('appName.modelName') 

y todo estaba bien.

+0

no ..... – alexvassel

6

Aparte de las cuestiones de orden, esto es falso:

cities = City.objects.filter(zip=self).distinct() 

No es un método en el interior, por lo que "sí" También habrá definido. Se ejecuta solo una vez, en el momento de creación de clase (es decir, cuando el módulo se importa por primera vez), por lo que el atributo creado sería un atributo de clase y tendría el mismo valor para todas las instancias. Lo que podría estar buscando es la siguiente:

@property 
def cities(self): 
    return City.objects.filter(zip=self).distinct() 

Debido a que este es un método en el interior, que no se ejecuta hasta que se accede, ordenando a los problemas ya no será un problema. Como Ozan señala, se trata de una duplicación de lo que Django relaciones de marcha atrás ya darle forma gratuita:

a_zip_code.city_set.all() 

Y puede utilizar related_name llamarlo lo que te gusta:

zip = models.ManyToManyField(ZipCode, related_name='cities') 
... 
a_zip_code.cities.all() 

Así que don' Creo que el problema de ordenar que originalmente le preguntó es incluso relevante para su situación. Cuando lo es, otros ya han señalado usando cadenas entrecomilladas en ForeignKey y declaraciones ManyToManyField para evitarlo.

Cuestiones relacionadas