Django: форма успешна, но изображение не загружено - PullRequest
0 голосов
/ 09 января 2020

MODELS.PY

class Campaign(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    campaign_image = models.ImageField(default="profilepic.jpg",upload_to="campaign_pictures")

FORMS.PY

class RaiseFundsFrom3(forms.ModelForm):
    class Meta:
        model = Campaign
        fields = ['campaign_image']

VIEWS.PY

@login_required
def raise_funds_medical_3(request):
    if request.method == 'POST':
        form = RaiseFundsFrom3(request.POST, request.FILES or None, instance=request.user)
        if form.is_valid():
            check = form.save(commit=False)
            check.save()
            return HttpResponse('form worked')
    else:
        form = RaiseFundsFrom3()
        return render(request,'funds/raise_funds_medical_3.html',{'form':form})

URLS.PY

path('raise/medical/photo', views.raise_funds_medical_3, name="raise_funds_medical_3"),

rise_funds_medical_3. html

<form method="post" enctype="multipart/form-data">
  {% csrf_token %}
  <div class="form-group pt-2">
    <small>Photo formats must be PNG / JPG / JPEG</small>
    <input type="file" name="campaign_image" />
  </div>
  <button class="btn btn-lg button_bfg_blue" type="submit"> <small><b> NEXT  </b></small> </button>
</form>

при отправке формы, я не появляется никаких ошибок, но изображение не загружено в нужную папку. тем не менее, в функции lift_funds_medical_3 в views.py, если я удаляю instance = request.user, изображение загружается, но я получаю следующую ошибку: Сбой ограничения NOT NULL: funds_campaign.user_id

Ответы [ 2 ]

3 голосов
/ 09 января 2020

Ваша форма ModelForm для Campaign, поэтому ее instance должно быть Campaign. Не назначайте request.user как instance!

Теперь ваша форма не включает в себя поле user, которое требуется для сохранения Campaign, поэтому вам следует назначить это в просмотр перед сохранением в базу данных:

campaign = form.save(commit=False)  # this gives your the form's instance
campaign.user = request.user  # this assigns the user
campaign.save()  # this commits to the database

Также вы должны обработать случай, когда форма недействительна. Это довольно просто, просто un-indent последний return в вашей функции просмотра, так что return render(...) также вызывается в случае, если form недопустим.

Наконец, вместо возврата ответа, когда форма верна, рекомендуется перенаправить в другое представление. Таким образом, когда пользователь обновляет страницу, форма больше не отправляется. Ваш окончательный код должен выглядеть следующим образом:

@login_required
def raise_funds_medical_3(request):
    if request.method == 'POST':
        form = RaiseFundsFrom3(request.POST, request.FILES or None)
        if form.is_valid():
            check = form.save(commit=False)
            check.user = request.user
            check.save()
            return redirect(<url_pattern>)
    else:
        form = RaiseFundsFrom3()
    return render(request,'funds/raise_funds_medical_3.html',{'form':form})
0 голосов
/ 09 января 2020

Дополнительный ответ на вопрос Диркгротена

Я пришел к полной ненависти к традиционному структурированию Django Представления на основе функций. Они могут быть перефакторированы путем инвертирования теста достоверности и добавления одной строки, чтобы присутствовал один и только один экземпляр формы. В результате IMO гораздо проще для чтения и легко обобщается для представления, отображающего две или более форм.

def raise_funds_medical_3(request):
    args = [request.POST, request.FILES or None] if request.method == "POST" else []
    form = RaiseFundsFrom3(*args)
    if request.method != "POST" or not form.is_valid():
        # unbound form or form not valid
        return render(request,'funds/raise_funds_medical_3.html',{'form':form})

    # form is valid so do the processing and redirect
    check = form.save(commit=False)
    check.user = request.user
    check.save()
    return redirect(<url_pattern>)

Если вы хотите обработать> 1 форму, тест становится

    if request.method != "POST" or any(
        [ not form.is_valid(), not form2.is_valid(), ...]):

который вызывает оценку .is_valid() для всех форм, даже если первая не была действительной, так что все сообщения об ошибках показываются пользователю.

В сложном бизнес-приложении, обработка успешного представления формы может занять несколько строк кода, чем в этом простом примере. Наличие его в конце, без отступа, изолированное от всех шаблонов, за исключением return redirect(...), делает вещи намного проще!

...