Django - Обновление только колонки FileField без переопределения других колонок

В Django у меня есть model:

class List(models.Model):
    item = models.CharField(max_length=200)
    document = models.FileField(upload_to='documents/', null=True, blank=True)

Также у меня есть страница, которая должна ТОЛЬКО загрузить файл в List.document для существующего списка: enter image description here

В views.py у меня есть

def upload(request, item_id):
    if request.method == 'POST':
        item = List.objects.get(pk=item_id)
        form = ListForm(request.POST, request.FILES, instance=item)
        if form.is_valid():
            form.save()
            messages.success(request, 'File saved successfully.')
        else:
            messages.error(request, f'File not saved properly: {form.errors.as_data()}')
        return redirect('home')

. Однако, поскольку форма не включает List.item, при нажатии Upload возникает ошибка File not saved properly: {'item': [ValidationError(['Это поле обязательно.'])]}.

Самым простым способом может быть добавление List.item в качестве скрытого элемента в html:

<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <div class="row">
        <div class="col-md-10">
            <input type="file" class="form-control" name="document" />
        </div>
        <div class="col-md-2">
            <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Upload</button>
        </div>
    </div>
</form>

Тем не менее, есть ли лучший способ преодолеть это? Может быть, есть варианты, позволяющие не перезаписывать существующие колонки?

Спасибо!

Я проследил за вашей ситуацией, но save() работает хорошо. Ниже приведены коды, которые я тестировал. Вы можете попробовать это.

models.py

from django.db import models

class List(models.Model):
    item = models.CharField(max_length=200)
    document = models.FileField(upload_to='documents/', null=True, blank=True)

forms.py

from django import forms
from .models import List

class ListForm(forms.ModelForm):
    class Meta:
        model = List
        fields = ['document']

views.py

from django.shortcuts import render, redirect
from .models import List
from .forms import ListForm

# Create your views here.
def upload(request, item_id):
    if request.method == 'POST':
        item = List.objects.get(pk=item_id)
        form = ListForm(request.POST, request.FILES, instance=item)
        if form.is_valid():
            form.save()
            # messages.success(request, 'File saved successfully.')
        else:
            # messages.error(request, f'File not saved properly: {form.errors.as_data()}')
            pass
        return redirect('home')
    return render(request, 'templates/upload.html', {'form': ListForm()})

upload.html

<!-- both forms are working -->

<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{form}}
    <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Upload</button>
</form>

<hr/>

<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <div class="row">
        <div class="col-md-10">
            <input type="file" class="form-control" name="document" />
        </div>
        <div class="col-md-2">
            <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Upload</button>
        </div>
    </div>
</form>

Вместо использования

form = ListForm(request.POST, request.FILES, instance=item)

, я должен использовать

from django.forms import modelform_factory
ListForm_ = modelform_factory(List, fields=("document",))

включать только необходимые поля (т.е. document).

Спасибо.

Вернуться на верх