При обращении к импортированной модели 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')
Вернуться на верх