Upload file with FileField and nginx just throw errors? - python

I'm new to Django, I'm learning how to handle uploading file with django, I did the same things with the document, but my nginx just throw out errors,
here is my views.py:
#csrf_exempt
def upload_view(request):
if request.method == 'POST':
form = UploadItemForm(request.POST, request.FILES)
if form.is_valid():
return HttpResponse('successfully uploaded')
else:
return HttpResponse('upload failed')
else:
if request.user.is_authenticated():
form = UploadItemForm()
return render(request,
'design/upload.html',
{'form': form,
'username': request.user.username})
else:
return HttpResponse("you have to login")
model.py
class Item(models.Model):
name = models.CharField(max_length = 100)
description = models.TextField(max_length = 1000)
uploadfile = models.FileField()
class UploadItemForm(ModelForm):
class Meta:
model = Item
my template:
<form enctype="multipart/form-data" method="post" action="/design/">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="upload" />
</form>
if I upload some text-based file (size is very small), everything is OK, when upload other formats, or large csv file, the code failed on
form = UploadItemForm(request.POST, request.FILES)
nginx says
Sorry, the page you are looking for is currently unavailable. Please
try again later.
I use nginx+uwsgi+django, so is it related to the uwsgi and nginx setup?

Ah, I solved it. For some unknown reason. It seems that, when the request size is beyond some threshold, nginx will put data on client_body_temp/ directory, for some reason(I don't know it), this directory in my setup is read-only by root???? change the permission, then everything goes fine

For additional info:
client_max_body_size 4M; //4mb
default_type text/plain; //file format
Here are the list of functions: http://nginx.org/en/docs/http/ngx_http_core_module.html
Read also this forum: http://forum.slicehost.com/index.php?p=/discussion/1714/nginx-413-when-uploading-file-1mb-or-larger/p1

Related

Empty request FILES in django

I have a Django model containing a fileField and a ModelForm which requests the user upload a file. Yet no matter what I seem to do, the request.FILES returned by the server does not contain anything. Here is the model:
class RepoFile(models.Model):
id = models.IntegerField(primary_key=True)
repo = models.FileField(blank=False, null=True, upload_to="repos/")
The ModelForm:
class RepoUpload(forms.ModelForm):
class Meta:
model = RepoFile
fields = ['repo']
widgets = {
'repo': ClearableFileInput(),
}
And the HTML
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
Also here is the view that I am using:
form = RepoUpload(request.FILES)
if form.is_valid():
print('this passed')
form.save()
I noticed that no matter what file I upload in the "Choose File" section, the form.is_valid() returns false. If I just use HTML and the view to send request.FILES to a manually created object, len(request.FILES) returns 0. Does anyone know of a solution?
you have a wrong init args in form, right is that:
form = RepoUpload(request.POST, request.FILES)
To avoid this error, is better to use:
form = RepoUpload(data=request.POST, files=request.FILES, )
additional kwargs for init:
data=None,
files=None,
auto_id='id_%s',
prefix=None,
initial=None,
error_class=ErrorList,
label_suffix=None,
empty_permitted=False,
field_order=None,
use_required_attribute=None,
renderer=None
Read more here:
https://docs.djangoproject.com/en/4.0/ref/forms/api/#django.forms.Form

Why my Model Form does not pass the validation

I am writing simple blog in django and I gotstuck on uploading files.
I want to create template wher user can write post and add multiple files. So firstrly i have created models:
class Post(models.Model):
title= models.CharField(verbose_name=u"post title", max_length=40, blank=False)
body= models.TextField(verbose_name=u"post body", blank=False)
author= models.ForeignKey(User, blank=False)
published= models.DateTimeField(verbose_name=u"data publikacji", blank=True, null=True)
class Add(models.Model):
post=models.ForeignKey(Post)
file=models.FileField(upload_to='adds', verbose_name=u"added files")
and after that i created template which looks like this:
{% block content %}
<div class="col-lg-6 col-md-offset-3">
<form enctype="multipart/form-data" method="post" adction="{% url 'create_post' %}">{% csrf_token %}
{{post_form|crispy}}
<input type="file" name="files" multiple/></br>
<input class="btn btn-success" style="width:100%" type="submit" value="Dodaj post"/>
</form>
</div>
{% endblock %}
after that i wrote simple view which would handle files and post creation:
def create_post(request):
if request.method== 'GET':
post_form=PostForm()
add_form=AddForm()
context={
'post_form': post_form,
}
return render(request, 'create_post.html', context)
else:
post_form=PostForm(request.POST)
if post_form.is_valid():
instance=post_form.save(commit=False)
instance.published=datetime.datetime.now()
instance.author=request.user
instance.save()
# import ipdb
# ipdb.set_trace()
for file in request.FILES.getlist("files"):
add_instance=AddForm()
add_instance.post=instance
add_instance.file=file
if add_instance.is_valid():
add_instance.save()
return redirect(reverse('AllPosts'))
but none of add_instance passes the validation "is_valid". But why?
And the second question is there any way to use Form in template against writing raw input for file? When i use AddForm i can only add one file what is logic.
You problem is that your form is always an unbounded form, which means that it is initialized without data. By data I mean POST or GET data from request or an instance of the model. unbounded form will always fail is_valid() and it doesn't make sense to manually assign anything to a form instance like add_instance = AddForm() then add_instance.post = instance.
django doc explains how to use a form.
You cannot upload multiple files with one single form because each form is a Add model form. You should really use ModelFormSet for your AddForm to add multiple model instances in one submit.
django doc explains how to use ModelFormSet.
By the way, I find the model name Add extremely confusing, consider changing it to Attachment or PostFile or something else.
Edit:
I didn't try it, but if you want one widget for multiple files, you can do this in views:
for upload_file in request.FILES.getlist('files'):
form = AddForm(request.POST, {'file': upload_file})
if form.is_valid():
new_file = form.save(commit=False)
new_file.post = instance
new_file.save()

Attaching a current User object to Django form

I am working on an app that has a section with with a file upload form for .txt fiels. I would like for the current user that is uploading the file to be added along with the file and the file name. Currently, I can do this successfully in the admin section but I just cant get it to save via the form itself. Any Ideas?
Here are the models:
class UploadedTextFile(models.Model):
file = models.FileField(upload_to="textfiles")
filename = models.CharField(max_length = 50)
username = models.ForeignKey(User, blank=True, null=True)
class UploadedTextFileForm(ModelForm):
class Meta:
model = UploadedTextFile
fields = ['file', 'filename']
Here is my view:
def inputtest(request):
#response for file being submited
if request.method == "POST":
form = UploadedTextFileForm(request.POST)
if form.is_valid():
new_form = form.save(commit=False)
new_form.username = request.user
new_form.save()
return render(request, 'about.html')
inputtest = UploadedTextFileForm()
return render(request, 'failed.html', {'inputtest': inputtest})
else:
inputtest = UploadedTextFileForm()
return render(request, 'inputtest.html', {'inputtest': inputtest})
Here is my html:
{% extends 'base.html' %}
{% block content %}
<form method="post">{% csrf_token %}
{{ inputtest.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
Doing it in the view (as you've shown) is the right way to do this. Most likely you're having problems because you've left username as a field on the form, and because the FK model field doesn't have blank=True set the form requires the field to be provided. You should explicitly declare just the subset fields that you want to accept user input for in the form's Meta class.
class UploadedTextFileForm(ModelForm):
class Meta:
model = UploadedTextFile
fields = ['file', 'filename']
I am not sure why you're rendering a different template when the form is not valid, but no matter what you're not providing the form object in the context. This means that you'll never see any errors the form detects, which is probably what's happening with this code - you're not seeing the error that username is not provided.

post form in django, get blank screen, broken or bug?

I've created a form in django which works fine on desktop browsers, but on mobile browsers when the form submits it just displays a blank screen (doesn't even load the title or an error), am I missing something?
If there's no way to make it work using post, how could I submit a form to locations/<zip code> or use get locations/?zip_code=<zip code>? (I'm a django noob, sorry)
here's the relevant code:
template:
<form action="" method="post">
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
form.py:
class ZipForm(forms.Form):
zip_code = forms.CharField(max_length=10)
views.py:
def zip(request):
if request.method == "POST":
form = ZipForm(request.POST)
if form.is_valid():
zip_code = form.cleaned_data['zip_code']
## get result
return render_to_response("zip.html",{
'title':'Closest Locations',
'results' : results,
'form' : form,
})
else:
form = ZipForm()
return render_to_response("zip.html", {
'form' : form,
'title' : 'Find Locations',
})
url.py:
url(r'^locations/$', 'app.views.zip'),
I wish there was a decent debugger for developing on mobile phones, ugh.
If the form is valid then you do all this fancy stuff... but you forgot to handle the case where the form isn't valid.

Form from Model with File Upload

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)

Categories

Resources