Django не может использовать pk для upload_to в сохраненном объекте

Я построил мастера в моем проекте. На первом этапе я создаю объект "Строительство" и сохраняю его в БД. На втором шаге я позволил пользователю загрузить изображение здания, сохраненное на первом шаге.

Изображение в модели здания.

Когда я попытался настроить путь сохранения изображения, я обнаружил, что "instance.pk" - это None.

То же самое происходит, если я пытаюсь получить доступ к каждому атрибуту модели, который должен быть в "экземпляре". Единственные атрибуты, к которым я могу получить доступ, - это те, которые я вручную установил в представлении (например, имя, описание,...)

Я не понимаю, почему это происходит. Может ли кто-нибудь объяснить это мне?

Часть модели:

 class Building(models.Model):
    utente = models.ForeignKey(User);
    nome = models.CharField(max_length=200, unique=True)
    descrizione = models.TextField(max_length=1000, blank=True)
    link = models.URLField(blank=True)
    foto = ImageField(upload_to=content_file_name, blank=True)
    ...

Content_file_name:

 def content_file_name(instance, filename):         
    estensione = '.jpg'       
    posizione_punto = filename.rfind('.')        
    if posizione_punto > 0:
            estensione = filename[posizione_punto:]
    return '/'.join(['buildings', str(instance.pk), 'vetrina'+estensione])

Часть представления (2-й шаг мастера):

 # I load the building from the db
 building = get_object_or_404(Building, pk=b_id)

 if request.method == 'POST':

       form = StepOneForm(request.POST, request.FILES)
       if form.is_valid():
            data = form.save(commit=False)
            building.data_update = datetime.datetime.now()
            building.nome = data.nome
            building.descrizione = data.descrizione
            building.link = data.link
            building.foto = data.foto

            building.save()

            ...

1 ответ

Решение

Во-первых, вы определили foto поле как foto = ImageField() наверное должно быть foto = models.ImageField()

Во-вторых, когда вы запускаете форму, вы не включаете instance аргумент (взгляните на документы). Это должно быть что-то вроде -

form = StepOneForm(request.POST, request.FILES, instance=building)

Вот как django знает, как добавить данные html-формы в существующий экземпляр. Если вы объявите свою форму, как это -

from django.forms import ModelForm

class BuildingForm(ModelForm):
    class Meta:
        model = Building

Затем, когда вы делаете data = form.save(commit=False) ваш data переменная на самом деле является экземпляром Building, И если вы уже сказали, что форма относится к конкретному экземпляру (например, building Вы объявляете в начале своего взгляда), затем data будет этот конкретный случай Building,

Это означает, что вы можете изменить свой код просмотра на -

def your_view(request):
    building = get_object_or_404(Building, pk=b_id)
    if request.method == 'POST':
        form = BuildingForm(request.POST, request.FILES, instance=building)
           if form.is_valid():
               building = form.save(commit=False)
               building.save()
    else: #...

Ознакомьтесь с документами Form и ModelForm.

Другие вопросы по тегам