Faz fim da matéria declaração em models.py (Django / Python)?

votos
5

Eu tenho algo parecido com isto em 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)

Quando eu fizer isso eu recebo:

NameError: name 'City' is not defined

É isto porque a ordem das questões de declaração? E se assim for, como posso fazer isso, porque de qualquer forma eu organizar isto, parece que eu estou indo para obter um NameError.

Obrigado.

Publicado 28/04/2009 em 02:39
fonte usuário
Em outras línguas...                            


6 respostas

votos
6

Para além das questões de ordem, isso é errado:

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

Não é dentro de um método, por isso, "eu" também será indefinido. Ele é executado apenas uma vez, em tempo de classe-criação (ou seja, quando o módulo é importada pela primeira vez), então o atributo criado seria um atributo de classe e têm o mesmo valor para todas as instâncias. O que você pode estar procurando é a seguinte:

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

Porque este é dentro de um método, que não é executado até que ele é acessado, questões de ordenação não será mais um problema. Como ozan assinala, esta é uma duplicação do que Django reverter relações já dar-lhe gratuitamente:

a_zip_code.city_set.all()

E você pode usar related_name para chamar do que quiser:

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

Então eu não acho que o problema de ordenação você pediu originalmente cerca é ainda relevante para sua situação. Quando é, os outros já apontaram usando cordas cotados em declarações ForeignKey e ManyToManyField para contorná-la.

Respondeu 28/04/2009 em 22:12
fonte usuário

votos
5

Quando você tem referências a classes definidas após, você pode usar esse truque:

attribute = models.ForeignKey('ClassDefinedAfterThis')
Respondeu 28/04/2009 em 03:00
fonte usuário

votos
3

Certa vez eu estava preocupado com o fim ... porque eu pensei que meus modelos abaixo só poderia referenciar modelos acima. Mas então percebi que você pode apenas fazer uma

models.ForeignKey('appName.modelName')

e tudo estava bem.

Respondeu 28/04/2009 em 03:42
fonte usuário

votos
2

Sim ordem não importa como os outros.

No entanto, a ocorrência deste problema é quase sempre vai ser uma indicação de que você está fazendo algo errado.

Neste caso, sua declaração:

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

... é tanto redundante prática e mau. Você pode encontrar as cidades relacionadas com um código postal, referindo-se city_set desse código postal em seus pontos de vista (ou seja, não em seu modelo!). Então, se zip é uma instância de ZipCode, você faria:

cities = zip.city_set.all()

Se você realmente quiser chamá-lo 'cidades' em vez de 'city_set' você pode usar o parâmetro related_name em sua declaração de M2M.

Respondeu 28/04/2009 em 07:07
fonte usuário

votos
2

Sim, a ordem não importa, mas o seu exemplo não parece certo para mim. Eu acho que você deve apenas estar usando uma chave estrangeira para o seu relacionamento muitos-para-um:

cities = models.ForeignKey(City)

Isto tem os detalhes sobre relacionamentos many-to-one com modelos do Django.

Editar:

Foi-me indicado nos comentários que as cidades na Europa pode ter várias cidades do mesmo código postal. Se você está procurando uma relação muitos-para-muitos aqui, você deve usar:

cities = models.ManyToManyField(City)

Isto está descrito na documentação do Django . O ponto é, este é um desses exemplos são muito mais clara do que o que é usado no exemplo.

Respondeu 28/04/2009 em 02:56
fonte usuário

votos
0

Encomendar matérias em Python. Esta discussão pode ser relevante para a sua pergunta. Também para os seus usos, você pode querer usar uma chave estrangeira única na classe CEP.

Respondeu 28/04/2009 em 02:55
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more