Как загрузить файл в поле FileField модели Django OneToOne с помощью формы?

У меня есть одна модель Detail, которая имеет OneToOne отношение с моделью по умолчанию User. У меня есть поле FileField в моей Detail модели, в которое я хочу загружать файлы с помощью форм из frontend/templates.

Я много работал над этим, но у меня ничего не получается. Мне нужна помощь, пожалуйста.

Мой models.py - это:

from django.db import models
from django.contrib.auth.models import User

class Detail(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    file = models.FileField(verbose_name="CSV File", upload_to='csv_files')
    file_desc = models.TextField("CSV File Description")

    def __str__(self):
        return ("{} ({} {})".format(self.user.email, self.user.first_name, self.user.last_name))

Мой forms.py - это:

from django.forms import ModelForm
from .models import Detail

class DetailForm(ModelForm):
    class Meta:
        model = Detail
        fields = ['file', 'file_desc']

Мой views.py - это:

from django.views import View

class UserAPI(View):
    template_name = 'accounts/user.html'

    def get(self, request):
        form = DetailForm(instance=request.user)

        context = {'form': form}
        return render(request, self.template_name, context)

    def post(self, request):
        form = DetailForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('user')

        context = {'form': form}
        return render(request, self.template_name, context)

и мой user.html (template) это:

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Submit</button>
</form>

Каждый раз, когда я перехожу на страницу localhost:8000/user, заполняю форму и нажимаю на кнопку Submit, на фронтенде появляется следующая ошибка: No File Chosen а также над кнопкой выбора файла появляется следующее утверждение: This field is required.

Я буду благодарен за помощь. Спасибо

Я думаю, что ваша форма ничего не сохраняет, потому что строка с form.is_valid() возвращает False.

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

Кроме того, вы не выводите ошибки, не относящиеся к полю, в HTML, поэтому вы не видите их на своей странице после отправки сообщения. Я предлагаю использовать пакет crispy-forms (вот ссылка ). Он обрабатывает такие вещи, как отрисовка формы из коробки.

Более того, указание аргумента ìnstance=request.user является некорректным, поскольку при наличии DetailForm экземпляр должен быть экземпляром модели Detail, а не User. Помните, instance kwarg необходим только в том случае, если вы хотите использовать эту форму для обновления.

Я предлагаю реализацию, подобную следующей:

forms.py

class DetailForm(ModelForm):
    class Meta:
        model = Detail
        fields = ['user', 'file', 'file_desc']

        widgets = {
            # I'm guessing you don't want to see the User field
            'user': HiddenInput()
        }

Релевантная часть views.py

def get(self, request):
    form = DetailForm()

    context = {'form': form}
    return render(request, self.template_name, context)

def post(self, request):
    form = DetailForm(request.POST, request.FILES, initial={'user': request.user.id})
    if form.is_valid():
        form.save()
        return redirect('user')


    context = {'form': form}
    return render(request, self.template_name, context)

Чтобы сделать этот ответ полным, я включу комментарий от @raphael, который исправил первую проблему вашего кода:

Убедитесь, что тег вашей формы выглядит следующим образом: <form method="post" enctype="multipart/form-data">

Некоторые ресурсы для подражания:

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