Django每次上传多张图片

6pp0gazn  于 2023-08-08  发布在  Go
关注(0)|答案(2)|浏览(167)

我想让用户上传多个图片后。类似于每个产品具有多个图像的电子商务平台。但到目前为止,图像还没有发送到数据库。
这是我目前为止的代码:
网址: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(upload_to="products")

字符串
网址: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>


网址:settings.py

STATIC_URL = '/static/'
MEDIA_URL = '/images/'

STATICFILES_DIRS = [
    BASE_DIR / 'static'
]

MEDIA_ROOT = os.path.join(BASE_DIR, 'static/images')
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')


项目urls.py

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


app urls.py

urlpatterns = [
    path("", views.createProject, name="create-project")
]

cetgtptt

cetgtptt1#

问题:

1.您创建了ProjectForm,它与Project模型相关,但image字段位于ProjectImage模型中。因此,image字段甚至没有传递给模板,并且您也没有在ProjectFrom中的fields=['title','describtion']中传递它。
1.您还没有在项目的urls.py中进行保存媒体文件的配置。

解决方案:

1.您应该在forms.py中创建两个表单,第一个ProjectForm将获取Project模型的数据,第二个ProjectImageForm将获取图像列表,然后使用request.FILES.getlist('image')可以在循环中逐个保存与特定示例相关的图像。
1.您应该在项目的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:在处理POST数据后,你应该总是返回HttpResponseRedirect,这个技巧并不特定于Django,它是一个很好的实践,就像tutorial4中所述的那样。
Note:基于函数的视图通常用snake_case编写,而不是camelCase,您可以将其从createProject更改为create_project
Note:ProjectImage模型的FileField中,将/作为upload_to='products/'添加到upload_to末尾。

pgccezyw

pgccezyw2#

ClearableFileInput不支持“multiple”,可以使用allow_multiple_selected。但仍然只允许上传一个项目。
这条路适合我
forms.py

class MultipleFileInput(forms.ClearableFileInput):
    allow_multiple_selected = True

class ProductImageForm(forms.ModelForm):
    class Meta:
        model = ProductImage
        fields = ('image',)
        widgets = {
            'image': MultipleFileInput()
       }

字符串

相关问题