我想让用户每篇文章上传多张图片。类似于每个产品有多个图像的电子商务平台。但到目前为止,这些图像还没有发送到数据库。
这是我目前的代码:
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')),
]
应用urls . py
urlpatterns = [
path("", views.createProject, name="create-project")
]
Issue:
-
您制作的
ProjectForm
与Project
模型相关,但image
字段在ProjectImage
模型中。所以,image
字段甚至没有传递给模板,你也没有在ProjectFrom
中传递fields=['title','describtion']
。 -
您没有在项目的urls.py中配置保存媒体文件。
解决方案:
-
您应该在forms.py中创建两个表单,第一个
ProjectForm
将获得Project
模型的数据,第二个ProjectImageForm
将获得图像列表,然后使用request.FILES.getlist('image')
您可以保存与特定实例相关的图像一个接一个地在循环中保存。 -
您应该在项目的url .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特有的,它是一个很好的实践,正如教程中所述。
Note:
基于函数的视图一般写在snake_case
而不是,你也可以从camelCase
改成createProject
create_project
。
Note:
在ProjectImage
模型的FileField中将upload_to后面的/
添加为upload_to='products/'
。
;在ClearableFileInput中不支持,您可以使用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()
}