Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does order of declaration matter in models.py (Django / Python)?

I have something like this in models.py

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)

When I do this I get:

NameError: name 'City' is not defined

Is this because the order of declaration matters? And if so, how can I do this, because either way I arrange this, it looks like I'm going to get a NameError.

Thanks.

like image 745
rick Avatar asked Apr 28 '09 01:04

rick


People also ask

How does model work in Django?

Django web applications access and manage data through Python objects referred to as models. Models define the structure of stored data, including the field types and possibly also their maximum size, default values, selection list options, help text for documentation, label text for forms, etc.

How do you inherit models in Django?

Models inheritance works the same way as normal Python class inheritance works, the only difference is, whether we want the parent models to have their own table in the database or not. When the parent model tables are not created as tables it just acts as a container for common fields and methods.

What does Django DB models model clean () do?

clean() This method should be used to provide custom model validation and to modify attributes on your model if desired.

What is primary key in Django model?

If you'd like to specify a custom primary key, specify primary_key=True on one of your fields. If Django sees you've explicitly set Field.primary_key , it won't add the automatic id column. Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).


2 Answers

Apart from order issues, this is wrong:

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

It is not inside a method, so "self" will also be undefined. It is executed only once, at class-creation time (i.e. when the module is first imported), so the attribute created would be a class attribute and have the same value for all instances. What you might be looking for is this:

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

Because this is inside a method, which is not executed until it's accessed, ordering issues will no longer be a problem. As ozan points out, this is a duplication of what Django reverse relations already give you for free:

a_zip_code.city_set.all()

And you can use related_name to call it what you like:

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

So I don't think the ordering issue you originally asked about is even relevant to your situation. When it is, others have already pointed out using quoted strings in ForeignKey and ManyToManyField declarations to get around it.

like image 90
Carl Meyer Avatar answered Nov 15 '22 09:11

Carl Meyer


When you have references to classes defined after, you can use this trick:

attribute = models.ForeignKey('ClassDefinedAfterThis')
like image 45
Alex. S. Avatar answered Nov 15 '22 10:11

Alex. S.