Django form FileField can't pass a validation - python

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 ;-)

Related

Django Forms: How do I use a selected object from dropdown menu?

I have a functioning dropdown menu filled with some objects from a database. When a user selects one, they should be directed to the objects appropriate page. Each object is a "Workout" and each workout has "Exercises". It is working, however, I am struggling to get the appropriate 'id' from the object that has been selected by the user. Below I will provide the view, template, url, and form.
view.py
#login_required
def routines(request):
"""This view will provide a dropdown list of all of the workouts of a specific user.
Once one is selected, the user will hit a submit button.
After submitted, a new page will show all the exercises for that workout"""
if request.method == "GET":
#if we have a GET response, provide a form with filled data
form = RoutineForm(request.GET, user=request.user)
#data needs to equal the object that was selected from the GET form
data = 1
if form.is_valid():
data=form.cleaned_data("workout")
form.instance.owner = request.user #make sure we have the right user
form.save()
return HttpResponseRedirect('routine_workouts_app:routines')
context = {'form':form, 'data':data}
return render(request, 'routine_workouts_app/routines.html', context)
#login_required
def routine(request, data):
"""I think this is the view that will display the information of a workout as of now.
Should be similar to the workout view."""
a_workout = Workout.objects.get(id=data)
#Make sure the topic belongs to the current user
if a_workout.owner != request.user:
raise Http404
exercises = a_workout.exercise_set.order_by('exercise_name')
context = {'a_workout': a_workout, 'exercises':exercises}
return render(request, 'routine_workouts_app/routine.html', context)
routines.html
<form action="{% url 'routine_workouts_app:routine' data %}" method="get">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Make Workout</button>
</form>
urls
path('routines/', views.routines, name='routines'), #this one deals with selecting a workout and submitting a form
#via routine/ shows the specific workout. just like workouts/int
path('routines/<int:data>/', views.routine, name='routine'), #this one displays the information based on the form
and the forms.py
class RoutineForm(forms.ModelForm):
"""This creates a form to work for Routine making"""
def __init__(self, *args, user=None, **kwargs): #this code helps to manage ownership of workouts.
super().__init__(*args, **kwargs)
self.fields['workout'].queryset = Workout.objects.filter(owner=user)
#info comes from the Routine model. Only field is 'workout' and labels is how we are going to identify the field on the webpage
class Meta:
model = Routine
fields = ['workout']
labels = {'workout': 'Workout'}
Basically, I would like to have data equal to the object that the user has selected in my routines function in views.py. From there, I can obtain the objects ID and direct the user to the right page. As of now, no matter when the use picks, they will be directed to the "Workout" with the ID of 1 (hence, why it is functioning but not to my desire).
I appreciate the help in advance. Also, may anyone recommend any textbooks that help improve Django skills such as this?
picture for reference:
You can use the redirect shortcut to make a redirection to a named url with arguments after validating the form. The argument are the workout id, which is stored in the routine instance created by the form.
<form action="{% url 'routine_workouts_app:routines' %}" method="get">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Make Workout</button>
</form>
from django.shortcuts import redirect
#login_required
def routines(request):
form = form = RoutineForm(request.GET or None, user=request.user)
if form.is_valid():
# workout_instance = form.cleaned_data("workout")
routine_instance = form.save(commit=False)
routine_instance.owner = request.user # make sure we have the right user
routine_instance.save()
return redirect('routine_workouts_app:routine', args=(routine_instance.workout.pk,))
context = {'form': form}
return render(request, 'routine_workouts_app/routines.html', context)

How to use data retrieved a form in Django (for a calculator app)

I'm new to Django. Even after reading, watching, and following many tutorials and guides, things still aren't coming together for me and I need help.
I'm making a very simple calculator app in preparation for a much more complicated calculator app that I will be refactoring/porting from a Python shell. The basic idea for the simply calculator is this: I have 4 pages on 1 app. They contain an add, subtract, multiply, and divide function respectively. I have a working side menu (using bootstrap and some copied code) to navigate between the pages. Each page has a form on it with two charfields and a submit button, and should return the result of the operation associated with the page. Right now I'm just focusing on the 'add' page since the others will just be a matter of copying.
Currently, I think I have a working form for getting two inputs, but I have no idea how to then get those two inputs as variables I can add to get the result.
Here's my code so far:
views.py
from __future__ import unicode_literals
from django.http import HttpResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from .forms import AddForm
#csrf_exempt
def web_adder(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 = AddForm(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 web_adder_out(form)
# if a GET (or any other method) we'll create a blank form
else:
form = AddForm()
return render(request, 'addercontent.html', {'form': form})
def web_adder_out(request, form):
return render(request, 'addercontentout.html', {'content':[form.addend0 + form.addend1]})
#haven't gotten to this stuff yet
def web_subtracter(request):
return render(request, 'subtractercontent.html')
def web_multiplier(request):
return render(request, 'multipliercontent.html')
def web_divider(request):
return render(request, 'dividercontent.html')
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.web_adder, name='web_adder'),
url(r'^web_sub$', views.web_subtracter, name='web_subtracter'),
url(r'^web_mul$', views.web_multiplier, name='web_multiplier'),
url(r'^web_div$', views.web_divider, name='web_divider'),
]
forms.py
from django import forms
class AddForm(forms.Form):
addend0 = forms.CharField(label='first addend', max_length=100)
addend1 = forms.CharField(label='second addend', max_length=100)
addercontent.html
{% extends "header.html" %}
{% block content %}
<p>This is a web adder</p>
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
addercontentout.html
{% extends "header.html" %}
{% block content %}
{% for c in content%}
<p>Result: {{c}}</p>
{% endfor %}
{% endblock %}
(I know I'm not showing a lot of html files but they shouldn't matter)
In the above code I know the form in web_adder is different from the form in web_adder_out, that's where I'm at a loss. Although I wouldn't be surprised to see other mistakes.
I'm using Python 2.7.
Thanks in advance.
You can process each individual field in the form like so:
form.cleaned_data['field_name']
this gets you the actual value of the field.
Example with your form would be:
form.cleaned_data['addend0']
which will give you the POST value of addend0 field.
Hope this helps!

Why is my Django form not raising any errors?

I have a simple form and whenever the user does something wrong on the form I'd like to raise a validation error on Django. The problem is that I set up the form validation but when the form is submitted with wrong values, it goes through. I was wondering why it's happening and how I can avoid that?
Here is the html form:
<form id="ask-project" method="post" action="{% url 'ask-project' %}">
{% csrf_token %}
<input required="required" class="form-control form-text required" id="prenom" name="prenom" type="text">
<button class="btn btn-default submit">Submit</button>
</form>
views.py:
def askProject(request):
if request.method == 'POST':
form = AskProjectForm(request.POST)
if form.is_valid():
save_it = form.save(commit=False)
save_it.save()
return redirect('/merci/') #success
forms.py:
class AskProjectForm(forms.ModelForm):
class Meta:
model = AskProject
fields = ['prenom']
def clean_prenom(self):
prenom = self.cleaned_data['prenom']
if len(prenom) < 3:
raise ValidationError('Votre prénom doit etre plus long que 1 caractère.')
return prenom
Am I doing something wrong?
With the pattern that you are using, this sort of problem is inevitable and order of the day. The first thing is not to render the form manually as you appear to be doing. That means you are not showing any feedback when the user enters invalid data. Consider using {{ form }}, {{ form.as_table }} etc or rendering the fields with all information as described here: https://docs.djangoproject.com/en/1.11/topics/forms/#rendering-fields-manually
Second problem is that you are redirecting when the form is submitted, regardless of whether it's valid or not. The recommended pattern is to redirect only when the form is valid. So even if you apply the suggestion in the first para, you are still not getting the required feedback. Consider implementing the form as suggested in the manual. A straight copy past follows
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(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('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
Finally getting onto the specific case of why your form validation doesn't work, add a print statement in your clean method to print out both the string and it's length see if it tallies (or if your method even gets called)

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/

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