Form from Model with File Upload - python

I'm trying to mimic the admin interface for the Photologue app on the front end. To achieve this, I have thus far created a bit of code in the view:
def galleryuploader(request):
GalleryFormSet = modelformset_factory(GalleryUpload)
if request.method == 'POST':
formset = GalleryFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
# do something. ... do what?
else:
formset = GalleryFormSet()
return render_to_response("cms_helper/gallery_upload.html", {
"formset": formset,
})
and a template:
<form method="post" action="">
{{ formset }}
<input type="submit" />
</form>
I'm using django's "form from models" method for generating this front-end form.
The problem: when I try to upload a file (because I am uploading photos to a photo gallery), and hit submit, it returns with a form error telling me that a required field was missing (the file).
I think I am not checking the request for any files, but even if I were to, I'm not quite sure how to. Here's some documentation about file uploads, but I haven't been able to decipher it yet.
If you have any suggestions about how to make this upload form work, I'd be veryyy happy to hear them. Thanks in advance!

Add the enctype="multipart/form-data" attribute to your form tag. Also you'll need to actually do something with the uploaded files. Here's the example from the django docs:
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
# Imaginary function to handle an uploaded file.
from somewhere import handle_uploaded_file
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
# you'll need to loop through the uploaded files here.
handle_uploaded_file(request.FILES['file'])
return HttpResponseRedirect('/success/url/')
else:
form = UploadFileForm()
return render_to_response('upload.html', {'form': form})
def handle_uploaded_file(f):
destination = open('some/file/name.txt', 'wb+')
for chunk in f.chunks():
destination.write(chunk)
destination.close()
(See the comment about halfway through)

Related

Save Multiple Files from Django Forms to Model

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)

how to manipulate user submitted text and display it with django?

I want to build a very simple webapp that takes a user's text, runs a function on it that alters it and then displays the altered text. I have the code for the function but everything else is unclear.
I am very new to django and just need a push in the right direction with this problem. At the very least, tell me what to google, I've went through several tutorials but neither of them dealt with this kind of task.
Thanks in advance!
Define a form; in forms.py under your app's folder
class MyForm(forms.Form):
myinput = forms.forms.CharField(max_length=100)
Define a function in your views.py
import .forms
def handle_form(request):
if request.method == 'POST': # If the form has been submitted...
form = MyForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('/thanks/') # Redirect after POST
else:
form = MyForm() # An unbound form
return render(request, 'handle_form.html', {
'form': form,
})
Add a template
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Of course you need to add it to your urls.py
Most info was copy pasted from: https://docs.djangoproject.com/en/1.8/topics/forms/

Django form FileField can't pass a validation

I see a lot of similar questions but can't found any answer. I need just to simply upload or process file using Django FileField. Here is what I have:
forms.py
class UploadForm(forms.Form):
packet_file = forms.FileField()
base.html
<form action="process" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
views.py
def index(request):
form = UploadForm() # An unbound form
return render(request, 'base.html', {'form': form})
def process(request):
if request.method == 'POST': # If the form has been submitted...
form = UploadForm(request.POST, request.FILES) # A form bound to the POST data
if form.is_valid():
So the index() handles initial rendering of the empty form. When I fill it and it goes to process() it always returns
This field is required.
Next to the FileField form field.
What's wrong here? Am I missing any general Django settings like MEDIA files storage or so? Is it's even necessary at this phase when I can't validate form?
Thanks a lot
TC
OK - it's my own stupidity as usual. I have two different applications and each one has its own sub-directory for templates. I thought Django uses that one within related directory first and when it's not found it goes to the project level.
But it doesn't work this way. So my I had two base.html templates for printing simple form, but the only the first one is being always called and it doesn't have enctype="multipart/form-data"
So that's it. Going back to study basic Django principles ;-)

Django Forms vs Templates

Sorry the inconvenient, but I am extremely newbie on Django. I imagined that Django would create the forms for me if I use forms.py, I would not need to create an input tag on template, so I created a test template only, since I created the forms.py. However, running my code I was told that my view didn't return an HttpResponse object, and I suspect it was due to my template having only text on it. Could you help me creating a template to have my forms working ? We can use the example posted above. I will paste it bellow:
def create_post(request):
if request.method == 'POST':
form = CreatePostForm(request.POST)
if form.is_valid():
my_model = form.save()
return redirect('/posts/')
else:
form = CreatePostForm()
c = {'form' : form}
return render(request,'create_post.html',c)
You should return render() instead of HttpResponse:
from django.shortcuts import render
def create_a_my_model(request):
...
return render(request, 'template.html', c)
template.html can be very primitive:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button>Save</button>
</form>
Also note that the good practice is to redirect to some page after the post request. This will prevent the double submit. So the whole code of your view will be:
from django.shortcuts import redirect, render
def create_a_my_model(request):
if request.method == 'POST':
form = MyModelForm(request.POST)
if form.is_valid():
my_model = form.save()
return redirect(my_model) # if the model has `get_absolute_url()`
else:
form = MyModelForm()
return render(request, 'template.html', {'form': form})
If you model doesn't have the get_absolute_url() method the you can redirect to any other url: return redirect('/success/page/')

uploading image in django

I'm writing a simple file uploader for a website. The user sees a form:
<form action="/user_profileform/" method="POST" enctype="multipart/form-data" name="uform" id="userform">{% csrf_token %}
{{form}}
<input type="submit" value="submit" name="usubmit">
</form>
and upon submit, I redirect to this function:
#csrf_exempt
def upload_file(request):
if request.method == 'POST':
print "arun";
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
return HttpResponseRedirect('/user_profileform/')
else:
print "ranjeet"
form = UploadFileForm()
return render_to_response('user_profile.html', {'form': form })
def handle_uploaded_file(f):
destination = open(settings.MEDIA_ROOT, 'wb+')
for chunk in f.chunks():
destination.write(chunk)
destination.close()
When I try this functionality out, I'll always get an exception:
IOError at /user_profileform/
[Errno 21] Is a directory: '/home/ghrix/ghrixbidding/media/images/'
You're trying to open settings.MEDIA_ROOT which is directory.
Because settings.MEDIA_ROOT is directory. You need to provide filename for handle.
Is better to use Model with FileField, because it generates unique file name in media automatically. It is described in https://docs.djangoproject.com/en/1.5/topics/http/file-uploads/

Categories

Resources