Python 如何使用formtools向导从Django文件系统存储中检索以多步骤形式上载的文件
我正在使用Django3.0和Python3.8.2开发一个广告网站。为了添加帖子,我使用了Django formtools向导。一切都很顺利。我可以保存各种形式的数据。但是,我无法从文件系统存储中检索文件以便保存它们。因此,我们非常感谢为实现这一目标或建议而提供的任何帮助。我想检索上传的文件,将它们保存到数据库,然后从向导(从文件系统存储)中删除它们。注意:没有错误,一切正常,除了上传的文件没有保存到数据库,即使它们在文件系统存储中可用。因此,我希望检索它们,以便能够将它们保存到数据库中。Python 如何使用formtools向导从Django文件系统存储中检索以多步骤形式上载的文件,python,django,Python,Django,我正在使用Django3.0和Python3.8.2开发一个广告网站。为了添加帖子,我使用了Django formtools向导。一切都很顺利。我可以保存各种形式的数据。但是,我无法从文件系统存储中检索文件以便保存它们。因此,我们非常感谢为实现这一目标或建议而提供的任何帮助。我想检索上传的文件,将它们保存到数据库,然后从向导(从文件系统存储)中删除它们。注意:没有错误,一切正常,除了上传的文件没有保存到数据库,即使它们在文件系统存储中可用。因此,我希望检索它们,以便能够将它们保存到数据库中。 下
下面是view类:
TEMPLATES = {"CommonForm": "towns/salehslist/ads_main_form.html",
"JobForm": "towns/salehslist/forms/jobPostForm.html",
}
FORMS = [
("CommonForm", CommonForm),
("JobForm", JobForm, JobImagesForm),
]
class PostWizard(SessionWizardView):
# The form wizard itself; will not be called directly by urls.py,
# but rather wrapped in a function that provide the condition_dictionary
_condition_dict = { # a dictionary with key=step, value=callable function that return True to show step and False to not
"CommonForm": True, # callable function that says to always show this step
"JobForm": select_second_step, # conditional callable for verifying whether to show step two
}
file_storage = FileSystemStorage(
location=os.path.join(settings.MEDIA_ROOT, "photos")
)
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
def done(self, form_list, form_dict, **kwargs):
# form_data = [form.cleaned_data for form in form_list]
# print(form_data)
data = {k: v for form in form_list for k, v in form.cleaned_data.items()}
data["posted_by"] = self.request.user
instance = Job.objects.create(**data)
print("YOU ARE HERE")
print(self.request.FILES.getlist("files"))
for file in self.request.FILES.getlist("files"):
print(file)
img_instance = JobImages.objects.create(job=instance, images=file)
img_instance.save()
return HttpResponse("<h1>Post Page </h1>")
以下是html模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% load static %}
{% load crispy_forms_tags %}
{% load i18n %}
<script type="text/javascript" src="{% static 'towns/assets/fontawesome-free-5-12-0-we/js/all.js' %}">
</script>
<link rel="stylesheet" type="text/css" href="{% static 'towns/assets/bootstrap-4.4.1/dist/css/bootstrap.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'towns/assets/fontawesome-free-5-12-0-we/scc/fontawesome.min.css' %}">
<!-- file uploader font -->
<link type="text/css" rel="stylesheet" media="all" href="{% static 'towns/assets/fileuploader-2.2/dist/font/font-fileuploader.css' %}" >
<link rel="stylesheet" type="text/css" href="{% static 'towns/style/forms/jobPostForm.css' %}">
</head>
<body>
<div class="container">
<div class="row h-100">
<div class="col-lg-6 my-auto">
<div class="breadcrumb">
<div class="ads-form-title">
Job Post
</div>
</div>
<form class="" action="" method="POST" enctype="multipart/form-data" novalidate id="jobPost">
{% csrf_token %}
{{ wizard.management_form }}
{{ wizard.form.media }}
<hr>
<div class="form-group">
<div>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form|crispy }}
{% endfor %}
{% else %}
{{ wizard.form|crispy }}
{% endif %}
</div>
</div>
<hr>
<!-- upload images -->
<!-- file input -->
<input type="file" name="files" class="files">
<center>
<button type="submit" class="btn btn-primary" style="position:relative; width: 33%; height: 100%;"> Submit </button>
</center>
</form>
</div>
</div>
</div>
<script type="text/javascript" src=" {% static 'towns/assets/jquery-3.5.0.min.js' %}">
</script>
<script type="text/javascript" src=" {% static 'towns/assets/bootstrap-4.4.1/dist/js/bootstrap.min.js' %}">
</script>
<script type="text/javascript" src="{% static 'towns/assets/fileuploader-2.2/dist/jquery.fileuploader.min.js' %}" >
</script>
</body>
</html>
{%load static%}
{%load crispy_forms_tags%}
{%load i18n%}
工作岗位
{%csrf_令牌%}
{{wizard.management_form}
{{wizard.form.media}
{{wizard.management_form}
{%if wizard.form.forms%}
{{wizard.form.management_form}
{wizard.form.forms%中窗体的%s}
{{form | crispy}}
{%endfor%}
{%else%}
{{wizard.form | crispy}}
{%endif%}
提交
当用户点击表单向导的submit
按钮时,调用def post()
方法<代码>def post()将
render_done
,即def done()
请求.files
为空的原因是,当前的请求
没有与其关联的文件或数据。点击done()
方法前面的submit
按钮时,所有数据和文件都会保存到会话中
由于我不知道您的表单是如何构造的,所以我不确定如何明确地解决您的问题。但下面这样做应该可以:
# iterate over all forms in the form_list
for form in form_list:
# check if current form has files
if bool(self.get_form_step_files(form)):
# if yes, do something
uploadedfiles = form.files
print(uploadedfiles)
for key, value in uploadedfiles.items():
jobimage = JobImage(job=?, image=value)
jobimage.save()
更新
没有模型、表单结构和模板,很难拿出完整的解决方案。我张贴了一个最低工作的例子
1。在型号中.py
class MyPost(models.Model):
field1 = models.CharField(max_length=50)
field2 = models.CharField(max_length=50)
class Photo(models.Model):
mypost = models.ForeignKey(MyPost, on_delete=models.CASCADE)
photo = models.FileField(blank=True, null=True)
def done(self, form_list, form_dict, **kwargs):
data = [form.cleaned_data for form in form_list]
# you can print out and inspect this data, and you will know
# the below code.
# you will need to modify data[0]['field1'] etc ...
print(data)
mypost = MyPost()
mypost.field1 = data[0]['field1']
mypost.field2=data[1]['field2']
mypost.save()
print('mypost')
print(mypost)
# the below part is for saving image files to model
for form in form_list:
# check which form has files
if bool(self.get_form_step_files(form)):
uploadedfiles= form.files
print(form.files)
for key, value in uploadedfiles.items():
photo = Photo(mypost=mypost,photo=value)
photo.save()
else:
print('not bool')
return render ##### whatever template you want to render
2。在表单中,您将不包括photoform,因为您正在尝试上载多个图像
from .models import MyPost, Image
from django import forms
class step_first_form(forms.ModelForm):
class Meta:
model = MyPost
fields = ['field1']
class step_second_form(forms.ModelForm):
class Meta:
model = MyPost
fields = ['field2']
字段2
和2个图像输入,您将其更改为:当您说:从文件系统存储中检索文件以便我可以保存它们时。什么意思,保存到模型?还有,为什么要保存它们,因为当您提交整个表单时,所有数据和文件都保存到模型中,对吗?不,不正确。Django formtools向导将数据保存在会话中,在done方法中,您必须检索数据并将其保存到数据库中。我做到了。我上载的图像将上载到文件系统存储。因此,我想检索并将它们保存到数据库中。在您的
def done
下,您已经将其保存到模型img_instance=JobImages.objects.create(job=instance,images=file)
,对吗?所以,为了检索,它是否与保存到模型中的任何其他文件一样?此代码不起作用。因为self.request.FILES.getlist(“文件”)返回空列表。所以没有保存任何文件。然而,当我检查照片文件夹时,我发现所有的图片都在那里。因此,代码“self.request.FILES.getlist(“FILES”)不是正确的方式。因此,我发布了一个问题,询问正确的方法。我更新了我的asnwer,使用bool
而不是isinstance
。即使使用isinstance
,您也应该得到非空的上传文件。在我的手里,它打印{'imagefile':}
。如果我检查管理,图像将保存到模型中。感谢您的回复。事实上,当我查看模板时,我发现只呈现了jobForm。未创建JobImagesForm。我仍然使用Jquery插件上传图片。然而,它们似乎没有随post请求一起提交。我更新了问题,加入了表单列表。你能展示一下你的模板吗?在上传文件的地方,是否有类似“为我使用两个模型”的字段。在第一个模板中,仅显示父模型中的字段。在第二个模板中,我并没有ImageForm,只是有几个具有不同名称的父表单字段。然后使用我上面的代码加上检索父模型的数据覆盖def done
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{wizard.form.field2}}
<input type="file" name ="imagefile1" >
<input type="file" name ="imagefile2" >
{% endif %}
</table>
.......
.....
.....
</form>
def done(self, form_list, form_dict, **kwargs):
data = [form.cleaned_data for form in form_list]
# you can print out and inspect this data, and you will know
# the below code.
# you will need to modify data[0]['field1'] etc ...
print(data)
mypost = MyPost()
mypost.field1 = data[0]['field1']
mypost.field2=data[1]['field2']
mypost.save()
print('mypost')
print(mypost)
# the below part is for saving image files to model
for form in form_list:
# check which form has files
if bool(self.get_form_step_files(form)):
uploadedfiles= form.files
print(form.files)
for key, value in uploadedfiles.items():
photo = Photo(mypost=mypost,photo=value)
photo.save()
else:
print('not bool')
return render ##### whatever template you want to render