Django inline-formset с полем изображения, которое не обновляется

У меня есть листинговая модель и фотомодель:

class Listing(models.Model):
    title = models.CharField(max_length=255)
    <more fields>...

class Photo(models.Model):
    image = models.ImageField(upload_to=create_file_path)
    listing = models.ForeignKey(Listing, related_name='photos')

Я использую CBV, UpdateView, для редактирования листинга. Я использую эту форму:

class ListingDetailForm(forms.ModelForm):
    class Meta:
    model = Listing
    exclude = []

и встроенный набор форм в forms.py, чтобы сделать возможным удаление/изменение изображения:

PhotoFormset = inlineformset_factory(Listing, Photo, fields='__all__', extra=1)

вот мой взгляд:

class ListingDetailView(UpdateView):
    model = Listing
    template_name = 'listing/listing_detail.html'
    form_class = ListingDetailForm
    success_url = '/store/'

    def get_context_data(self, **kwargs):
        self.object = self.get_object()
        context = super(ListingDetailView, self).get_context_data(**kwargs)
        if self.request.POST:
            context['form'] = ListingDetailForm(self.request.POST, instance=self.object)
            context['photo_form'] = PhotoFormset(self.request.POST, self.request.FILES, instance=self.object)
        else:
            context['form'] = ListingDetailForm(instance=self.object)
            context['photo_form'] = PhotoFormset(instance=self.object)
        return context

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        photo_form = PhotoFormset(self.request.POST)
        print photo_form.is_valid()
        if form.is_valid() and photo_form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

    def form_valid(self, form):
        print 'in form valid for update'
        context = self.get_context_data()
        base_form = context['form']
        photo_form = context['photo_form']
        # print base_form
        # print photo_form
        if base_form.is_valid() and photo_form.is_valid():
            print 'forms are valid for update'
            base_form.save()
            photo_form.save()
            return super(ListingDetailView, self).form_valid(form)
        else:
            return self.render_to_response(self)

и соответствующий раздел шаблона:

{% block body %}
<form action="" method="post">
    {% csrf_token %}
        {% for field in form %}
            {{ field.errors }}
            {{ field.label_tag }} {{ field }}<br><br>
        {% endfor %}
        {% for field in photo_form %}
            {{ field.errors }}
            {{ field.label_tag }} {{ field }}<br><br>
        {% endfor %}
    {{ photo_form.management_form }}
    <input type="submit" value="Update" />
</form>
{% endblock %}

Проблемы, которые у меня возникают:

1) Если к объявлению прикреплена фотография, через админку фотоформа не проходит валидацию, если я ничего не делаю с фотоформой, т.е. изменить только поля из модели листинга. Форма фото не отображает ошибок, когда страница перезагружается после недействительного.

2) выбор новой фотографии не меняет текущую фотографию, форма фотографии не проверяется и не отображает ошибок.

3) если в настоящее время нет фотографии, относящейся к списку, попытка добавить одну проверяет через форму, но фактически не сохраняет фотографию, связанную с этим списком.

Удаление изображения, если оно прикреплено к листингу, работает отлично. Удаление изображения и обновление какого-либо другого поля из списка работает. Если нет обновления изображения, работает только поле списка. Добавление второй фотографии в список через форму не работает и не выводит ошибок формы.


person Rob    schedule 09.09.2015    source источник


Ответы (1)


Я заметил несколько проблем с вашей формой.

  1. Вам необходимо включить enctype="multipart/form-data" в атрибуты формы, иначе вы не сможете отправлять данные файла на сервер.
  2. Я бы использовал методы Django для рендеринга формы (form.as_p, form.as_table или form.as_ul), если вам абсолютно необходимо использовать ручной рендеринг, следуйте официальному руководству: наборы моделей
  3. В методе публикации в вашем наборе форм отсутствуют ФАЙЛЫ и экземпляр

После внесения этих изменений ваш набор форм должен работать нормально.

person Alex Carlos    schedule 09.09.2015
comment
Спасибо за этот ответ @Alex....Сколько раз enctype="multipart/form-data" мне будет больно. - person danidee; 25.08.2017
comment
Я даже не могу сосчитать, сколько раз это доставляло мне неприятности. Вот почему это первое, на что я смотрю, когда возникают проблемы с формой. - person Alex Carlos; 28.08.2017