Looking to upload 2 files into a Django Form using HTML5 (since it supports multi-file upload). The problem I'm facing is it's targets the 1st one for uploading. It knows there are 2 files, because when it saves, it saves twice (as per the for loop below). I thought to use the dictionary to loop over the names, but I receive an error that says this keyword can't be an expression. Maybe this is something simple, but if you need more, I can provide. Just a note, I did not use the forms.py for the file upload, but instead just the regular HTML <input tag. Thanks.
#page.html
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form_a.as_p }}
<input type="file" name="img" multiple>
<input type="submit" value="Submit" />
</form>
#models.py
def contact(request):
if request.method == 'POST':
form_a = RequestForm(request.POST, request.FILES)
if form_a.is_valid():
#assign form data to variables
saved_first_name = form_a.cleaned_data['First_Name']
saved_last_name = form_a.cleaned_data['Last_Name']
saved_department = form_a.cleaned_data['Department']
saved_attachments = request.FILES.getlist('img')
#create a dictionary representing the two Attachment Fields
tel = {'keyword1': 'Attachment_2', 'keyword1': 'Attachment_1'}
for a_file in saved_attachments:
#for every attachment that was uploaded, add each one to an Attachment Field
instance = Model(
Attachment_1=a_file,
Attachment_2=a_file
)
instance.save()
all_together_now = Model(First_Name=saved_first_name, Last_Name=saved_last_name,
Department=saved_department, Attachment_1=???, Attachment_2=???)
#save the entire form
all_together_now.save()
else:
#just return an empty form
form_a = RequestForm()
return render(request, 'vendor_db/contact.html', {'form_a': form_a})
Here is a way that worked for me. I loop each occurrence of an InMemoryUploadedFile in request.FILES and re-assign it back onto request.FILES, then save each one by one.
forms.py
class PhotosForm(forms.ModelForm):
file = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
class Meta:
model = Photos
fields = ['file']
views.py
def photos(request):
photos = Photos.objects.all()
if request.method == 'GET':
form = PhotosForm(None)
elif request.method == 'POST':
for _file in request.FILES.getlist('file'):
request.FILES['file'] = _file
form = PhotosForm(request.POST, request.FILES)
if form.is_valid():
_new = form.save(commit=False)
_new.save()
form.save_m2m()
context = {'form': form, 'photos': photos}
return render(request, 'app/photos.html', context)
Related
I currently have a model that is called services, shown here...
class Services(models.Model):
service_sku = models.AutoField(primary_key=True)
name = models.CharField(max_length=200, null=True)
price = models.FloatField(null=True)
forms.py
class ServiceForm(forms.ModelForm):
class Meta:
model = Services
fields = '__all__'
Based on the code shown above, I have two views, one will create instances of the model above and the other view will update the instance, as follows
def NewServices(request):
form = ServiceForm()
if request.method == 'POST':
form = ServiceForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('/')
return render(request, 'accounts/new_services.html', {'form': form})
def EditServices(request,pk):
service = Services.objects.get(service_sku=pk)
form = ServiceForm(instance=service)
if request.method == 'POST':
form = ServiceForm(request.POST, instance=service)
if form.is_valid():
form.save()
return redirect('/')
context = {'form':form}
return render(request, 'accounts/edit_services.html',context)
Template as follows
<div class="row">
<div class="col-md-7">
<div class="card card-body">
<form action="" method="POST">
{% csrf_token %}
{{form}}
<hr>
<input type="submit" name="Update">
</form>
</div>
</div>
</div>
Is it possible to show a readyonly of the service_sku within in my template form, when a instance needs to be updated and when a service_sku readonly is shown to be autogenerated in a template when creating a instance?
Yes. You can include the field in a form, so likely you should make a separate one to update:
class ServiceEditForm(forms.ModelForm):
service_sku = forms.IntegerField(disabled=True)
class Meta:
model = Services
fields = ('service_sku', 'name', 'price')
In the form you then simply use that new form:
def EditServices(request,pk):
service = Services.objects.get(service_sku=pk)
if request.method == 'POST':
form = ServiceEditForm(request.POST, request.FILES, instance=service)
if form.is_valid():
form.save()
return redirect('/')
else:
form = ServiceEditForm(instance=service)
context = {'form':form}
return render(request, 'accounts/edit_services.html', context)
Using disabled=True [Django-doc] does not only make sure the field is disabled at the client side, but it will also prevent a person to make a malicious POST request.
I am trying to save a file and some other details in django using forms.
And I only want it to save a CharField and a FileField but not the country field.
For country field I want it to take its value through a post request.
But the form isn't saving. The errors says "data didn't validate".
Also this method works fine if I don't use a FileField.
models.py
class Simple(models.Model):
name = models.CharField(max_length=100)
city = models.FileField(upload_to='marksheet')
country = models.CharField(max_length=100)
forms.py
class SimpForm(forms.ModelForm):
class Meta:
model = Simple
fields = ['name','city']
A snippet from upload.html
<form action="upload" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<label>Test input</label>
<input type="text" name="country">
{{form.name}}
{{form.city}}
<button type="submit">Submit</button>
</form>
views.py
def upload(request):
if request.method == 'POST':
a = request.POST.get('country')
form = SimpForm(request.POST,request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.country = a
post.save()
return HttpResponse('saved')
else:
return HttpResponse('ERROR SAVING')
else:
form = SimpForm()
return render(request,'upload.html',{'form':form})
You are not passing request.FILES in your form. You should pass it like this:
form = SimpForm(request.POST, request.FILES)
More information on file uploads can be found in documentation.
data cannot be saved in form.I wrote html like
<form action="/app/save" method="POST">
<input id="classname" name="classname">
<input id="score" name="score">
<input id="course" name="course">
<button type="submit">SEND</button>
</form>
in forms.py
from django import forms
from .models import Student
class SaveForm(forms.ModelForm):
class Meta:
model = Student
fields = ("classname", "score", "course")
in views.py
#csrf_exempt
def save(request):
save_form = SaveForm(request.POST or None)
print(save_form.is_valid())
if request.method == "POST" and save_form.is_valid():
item = save_form.save(commit=False)
classname = request.POST.get("classname", "")
score = request.POST.get("score", "")
course = request.POST.get("course", "")
item.classname = classname
item.score = score
item.course = course
item.save()
return render(request, 'index.html')
in models.py
from django.db import models
class Student(models.Model):
classname = models.CharField(max_length=100)
score = models.CharField(max_length=100)
course = models.CharField(max_length=100)
When I run this codes ,put data A in classname& 80 in score&Math in course of html and put SEND button,save method can be called but data cannot be saved.print(save_form.is_valid()) shows False.I really cannot understand why I can't send data.What is wrong in my codes?How should I fix this?
Okay a few things here;
Why is score a charfield? If it's a %, shouldn't it be an int?
Student model doesn't have any foreign keys, so there's really no need to use commit = false in your save.
Creating inputs for each item on your form in html is definitely the long way to do it. The best way to do this in your html is simply to use {{form}}. To do this, you'll need to pass the form as a variable in context in your views.py.
Without being mean, are you very early in to the django beginner tutorial? If so, I would recommend moving forward through that before trying to continue your current project. It'll really help you. Here's what I would suggest as a views.py
def save(request):
if request.method == "POST":
save_form = SaveForm(request.POST)
print(save_form.is_valid())
if(save_form.is_valid()):
save_form.save()
return HttpResponseRedirect('New-destination-URL')
save_form = SaveForm()
context['form'] = save_form
return render(request, context, 'index.html')
and in index.html:
form action="/app/save" method="POST">
{{form}}
</form>
You do it wrong, you have to handle both situations - when you are on page at first time, and time when form is filled with data.
Try to change your views to this :
if request.method == "POST":
save_form = SaveForm(request.POST)
...
else:
save_form = SaveForm()
return render(request, 'index.html', {'save_form': save_form)
and then try to put this in template:
<form action="/app/save" method="POST">
{{ save_form.as_p }}
<button type="submit">SEND</button>
</form>
i want to manage(move and rename)files that user upload :
my upload form(html):
<form action="../valid_upload/" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<input type="submit" name="send" value="send" />
</form>
my form(django part):
class UploadImageForm(forms.Form):
image = forms.FileField()
name = forms.CharField(max_length=100)
about = forms.CharField(widget=forms.Textarea)
taq1 = forms.CharField(max_length=100)
taq2 = forms.CharField(max_length=100)
taq3 = forms.CharField(max_length=100)
url.py(just a one line):
url(r'valid_upload/', views.valid_upload, name='valid_upload'),
and view.py(just a part of that):
if 'username' in request.session:
if request.method == 'POST':
if 'image' in request.FILES:
form = UploadImageForm(request.POST, request.FILES)
if form.is_valid():
# Here goes the documentation code
return HttpResponse(request.FILES['image'].content_type)
//here i want to rename and move uploaded files
else:
return redirect('/upload_image')
else:
return redirect('/login/')
i want to know how to rename uploaded file and move them on my directories.if you can help me :)
You can pass the request data to your form, and let the form manage your needs. Here is an example:
if 'username' in request.session:
if request.method == 'POST':
if 'image' in request.FILES:
form = UploadImageForm(request.POST, request.FILES)
if form.is_valid():
# Here goes the documentation code
return HttpResponse(request.FILES['image'].content_type)
//here i want to rename and move uploaded files
else:
return redirect('/upload_image')
else:
return redirect('/login/')
You can use a django model too.
Here is the documentation:
https://docs.djangoproject.com/en/1.11/topics/http/file-uploads/
I have been going through the Django forms 'tutorial'. Once I had read through the tutorial, I tried modifying it to suit my needs and customize it to learn it Django forms well. I discovered whenever I modified the form, the website would not update. I assume its an error with my code, but I have not been able to find it.
# views.py
def contact(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = ContactForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/message_recived/')
# forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(label='Name', max_length=100)
email = forms.EmailField(label='Email', max_length=100)
message = forms.CharField(label='Message', max_length=500)
# models.py
from django.db import models
class Contact(models.Model):
name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
message = models.CharField(max_length=500)
and here is the contact.html template:
#contact.html
{% extends "BlogHome/headerAndFooter.html" %}
{% block content %}
<script>
document.title = "Pike Dzurny - Contact"
</script>
<form action="/message_recived/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
Did I do something wrong? I have tried clearing my browsers cache, using a new browser, and obviously refreshing it.
Looks like your forget to render response inside your view.
Also you need to include form into context to render template right.
Try to change view as follow:
def contact(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = ContactForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/message_recived/')
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})