[英]How to retrieve files from Django FileSystemStorage uploaded in a multisteps form using formtools wizard
I am using Django 3.0 and python 3.8.2 to develop an ads website.我正在使用 Django 3.0 和 python 3.8.2 来开发广告网站。 To add a post, I used Django formtools wizard.
要添加帖子,我使用了 Django formtools 向导。 It worked and everything goes nicely.
它奏效了,一切顺利。 I could save the multiform data.
我可以保存多格式数据。 However, I could not retrieve the files from the FileSystemStorage so I can save them.
但是,我无法从 FileSystemStorage 中检索文件,因此我可以保存它们。 Hence, any help to achieve this or suggestion is much appreciated.
因此,非常感谢任何有助于实现这一点或建议的帮助。 I want to retrieve uploaded files, save them to the data base and then delete them from the wizard (from the FileSystemStorage).
我想检索上传的文件,将它们保存到数据库中,然后从向导(从 FileSystemStorage)中删除它们。 Note: there is no error and everything is working except that the uploaded files are not saved to the data base even though they are available in the FileSystemStorage.
注意:没有错误,一切正常,除了上传的文件没有保存到数据库中,即使它们在 FileSystemStorage 中可用。 Thus, I want to retrieve them to be able to save them to the data base.
因此,我想检索它们以便能够将它们保存到数据库中。
Here is the view class:这是 class 的视图:
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>")
Here is the url:这是 url:
url(r'^post/$', PostWizard.as_view(FORMS, condition_dict = PostWizard._condition_dict)),
Here is the html template:这是 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>
When user hit submit
button of the form wizard, def post()
method is called.当用户点击表单向导的
submit
按钮时,将调用def post()
方法。 def post()
will def post()
将
render_done
, which is def done()
render_done
,也就是def done()
The reason why your request.files
is empty is because, the current request
does not have files or data associated with it.您的
request.files
为空的原因是,当前request
没有与之关联的文件或数据。 All your data and files are saved to the session when you hit the submit
buttons which are preceding the done()
method.当您点击
done()
方法之前的submit
按钮时,您的所有数据和文件都会保存到 session 中。
Since I do not know how your form is structured, I am not sure how to definetely solve your problem.由于我不知道您的表格的结构,我不确定如何明确地解决您的问题。 But something like below should do:
但是像下面这样的事情应该做:
# 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()
Update wihtout your model, form structure, and template, it is difficult to come out with complete solution.没有你的model、表格结构和模板的更新,很难拿出完整的解决方案。 I am posting a minimum working example.
我发布了一个最低限度的工作示例。
1. in models.py 1.在models.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)
2. In forms, you will not include photoform, because you are trying to uplaod more than one images. 2. 在 forms 中,您不会包含 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']
field2
and 2 image inputs, you will change it to:field2
和 2 个图像输入,您将其更改为:<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>
enctype="multipart/form-data"
otherwise your files will not be uploaded.enctype="multipart/form-data"
否则您的文件将不会被上传。 4. in views.py 4.在views.py中
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.