Django загрузка нескольких изображений в одно сообщение

Здравствуйте, я хочу позволить пользователю загружать несколько изображений в каждый пост. Аналогично платформе электронной коммерции с несколькими изображениями для каждого продукта. Но до сих пор изображения не отправляются в базу данных.

Вот мой код на данный момент:

models.py:

class Project(models.Model):
    title = models.CharField(max_length=200)
    describtion = models.TextField(null=True, blank=True)

class ProjectImage(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    image = models.FileField()

forms.py

class ProjectForm(ModelForm):
    image = forms.ImageField(widget=ClearableFileInput(attrs={'multiple':True}))
    class Meta:
        model = Project
        fields = ['title', 'describtion']

views.py:

def createProject(request):
    form = ProjectForm()

    if request.method == 'POST':
        form = ProjectForm(request.POST)
        images = request.FILES.getlist('image')
        if form.is_valid():
            project = form.save()
            for i in images:
                ProjectImage(project=project, image=i).save()
    context = {'form':form}
    return render(request, 'projects/project_form.html', context)

project_form.html:

<form class="form" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {% for field in form %}
    <div class="form__field">
        <label for="formInput#text">{{field.label}}</label>
        {{field}}
    </div>
    {% endfor %}
    <input type="submit" name="" id="">
</form>

Выпуск:

  1. Вы сделали ProjectForm, который относится к модели Project, но поле image находится в модели ProjectImage. Таким образом, поле image даже не передается в шаблон, и вы также не передали его в fields=['title','describtion'] в ProjectFrom.

  2. Вы не сделали конфигурации для сохранения медиа файлов в urls.py.

    проекта.

Решение:

  1. Вы должны сделать две формы в forms.py, первая ProjectForm, которая будет получать данные для модели Project, а вторая ProjectImageForm, которая будет получать список изображений, затем используя request.FILES.getlist('image') вы можете сохранять изображения, которые относятся к определенному экземпляру по одному в цикле, как вы пытались сохранить.

  2. Вы должны сделать медиа конфигурации в urls.py

    проекта.


Попробуйте код ниже:

forms.py

from django import forms
from django.forms import ClearableFileInput
from .models import Project, ProjectImage


class ProjectForm(forms.ModelForm):

    class Meta:
        model = Project
        fields = ['title', 'describtion']


class ProjectImageForm(forms.ModelForm):
    class Meta:
        model = ProjectImage
        fields = ['image']
        widgets = {
            'image': ClearableFileInput(attrs={'multiple': True}),
        }

views.py

from django.http import HttpResponse
from django.shortcuts import redirect, render
from .forms import ProjectImageForm, ProjectForm
from .models import Project, ProjectImage


def createProject(request):
    form = ProjectForm()
    form2 = ProjectImageForm()

    if request.method == 'POST':
        form = ProjectForm(request.POST)
        form2 = ProjectImageForm(request.POST, request.FILES)
        images = request.FILES.getlist('image')
        if form.is_valid() and form2.is_valid():
            title = form.cleaned_data['title']
            describ = form.cleaned_data['describtion']
            print(title, describ)
            project_instance = Project.objects.create(
                title=title, describtion=describ)
            print('-------------------------------------------')
            print(project_instance)
            print('-------------------------------------------')

            for i in images:
                ProjectImage.objects.create(project=project_instance, image=i)
            return redirect('thanks')

    context = {'form': form, 'form2': form2}
    return render(request, 'projects/project_form.html', context)


def thanks(request):
    return HttpResponse('<h1>Form saved.</h1>')

project_form.html или файл шаблона:

<form class="form" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{form.title.label_tag}}
    {{form.title}}
        <br><br>
    {{form.describtion.label_tag}}
    {{form.describtion}}
        <br><br>
    {{form2.image.label_tag}}
    {{form2.image}}
        <br><br>

    <input type="submit" name="" id="">
</form>

urls.py проекта

from django.conf.urls.static import static
from django.conf import settings
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('projects.urls'))
]


if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL,
                          document_root=settings.MEDIA_ROOT)

urls.py приложения

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('home.urls'))
]

Ваши models.py и settings.py могут оставаться одинаковыми, но рекомендуется использовать MEDIA_URL = 'media/' и MEDIA_ROOT = os.path.join(BASE_DIR, 'media/'), тогда вы должны сделать вложенные папки внутри них для сохранения изображений или любых файлов.

Note: Вы всегда должны возвращать HttpResponseRedirect после работы с POST данными, совет не относится к Django, это хорошая практика в целом, как указано в tutorial4.

Note: Представления на основе функций обычно пишутся в snake_case, а не в camelCase, вы можете изменить его на create_project из createProject.

Note: Добавьте / в конце upload_to как upload_to='products/' в поле image в ProjectImage модели.

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