При обращении к импортированной модели Django возникает ошибка 'local variable referenced before assignment'.
Я пытаюсь импортировать модель в мое представление Django, а затем запросить все объекты, отсортировать их и выполнить итерацию по ним. Я не получаю никаких ошибок при импорте модели, однако при попытке запросить модель с помощью songs = song.objects.all()#.order_by('-release_date')
, я получаю ошибку:
UnboundLocalError at /hotline/dbm
local variable 'song' referenced before assignment
/home/path/to/site/views.py, line 82, in dbm
songs = song.objects.all()#.order_by('-release_date')
Я не понимаю, в чем проблема, поскольку переменная song
явно импортирована из моего models.py
файла, и я не получаю никаких ошибок при ее импорте - так почему же Python не распознает song
как то, что я импортировал из моего models.py
файла?
Мой models.py
файл:
class song(models.Model):
name = models.TextField()
file = models.FileField()
release_date = models.DateTimeField(default=timezone.now)
class Meta:
verbose_name = 'Song'
verbose_name_plural = f'{verbose_name}s'
мой views.py
файл:
#list of modules removed to keep code clean
from .models import *
@csrf_exempt
def dbm(request: HttpRequest) -> HttpResponse:
songs = song.objects.all()#.order_by('-release_date')
response = request.POST.get('Digits')
if response == None:
vr = VoiceResponse()
vr.say("Please choose a song, and then press pound")
vr.pause(length=1)
with vr.gather(finish_on_key='#', timeout=6, numDigits="1") as gather:
for song, num in songs:
gather.pause(length=1)
gather.say(f"For {song.name}, please press {num}")
vr.redirect(reverse('dbm'))
return HttpResponse(str(vr), content_type='text/xml')
elif response != None:
vr = VoiceResponse()
vr.say("hi")
return HttpResponse(str(vr), content_type='text/xml')
Спасибо!
Я не понимаю, в чем проблема, поскольку переменная song явно импортирована из моего файла models.py
.
Да, но в вашей функции вы также работаете с локальной переменной с именем song
, действительно:
for song, num in songs:
# …
Это означает, что Python говорит, что song
- это локальная переменная, и поэтому отказывается искать ее вне функции.
Но я думаю, что основная проблема заключается в том, что классы обычно пишутся на PascalCase
, а не на , поэтому вам, вероятно, лучше переименовать модель snake_case
Song
, а не . Поскольку локальным переменным присваиваются song
snake_case
имена, это позволяет избежать столкновений, поэтому:
# 🖟 not song
class Song(models.Model):
name = models.TextField()
file = models.FileField()
release_date = models.DateTimeField(default=timezone.now)
class Meta:
verbose_name = 'Song'
verbose_name_plural = f'{verbose_name}s'
тогда вид будет выглядеть так:
from .models import Song
@csrf_exempt
def dbm(request: HttpRequest) -> HttpResponse:
songs = Song.objects..order_by('-release_date')
response = request.POST.get('Digits')
if response is None:
vr = VoiceResponse()
vr.say('Please choose a song, and then press pound')
vr.pause(length=1)
with vr.gather(finish_on_key='#', timeout=6, numDigits="1") as gather:
for song, num in songs:
gather.pause(length=1)
gather.say(f"For {song.name}, please press {num}")
vr.redirect(reverse('dbm'))
return HttpResponse(str(vr), content_type='text/xml')
else:
vr = VoiceResponse()
vr.say('hi')
return HttpResponse(str(vr), content_type='text/xml')
Note: Please do not use wildcard imports [quantifiedcode.com]. It makes the statement less predictable, it can easily result in failing code if you later decide to change what is exported in a certain module, and furthermore it can override variables.
в вашем коде строчная песня конфликтует с именем класса.
когда вы используете:
from .models import *
django импортирует класс song и присваивает ему локальное имя song.
for song, num in songs:
Однако интерпретатор предполагает, что song в вашей функции ссылается на локальную переменную (а не на класс модели), поскольку цикл for временно создает локальную переменную
а в Django классы моделей должны следовать соглашению об именовании PascalCase.
models.py:
class Song(models.Model):
name = models.TextField()
file = models.FileField()
release_date = models.DateTimeField(default=timezone.now)
views.py
from .models import Song
@csrf_exempt
def dbm(request: HttpRequest) -> HttpResponse:
songs = Song.objects.all()#.order_by('-release_date')