I am working with Django forms and for some reason, this form will not validate! It submits alright, or at least the runserver shows an http post response with code 200 (ok). For some reason though, my form will not pass the is_valid test!
views.py:
def new_show(request):
if request.method == 'POST':
img_form = ImageForm(request.POST, request.FILES)
show_form = NewShowForm(request.POST)
if show_form.is_valid():
new_Show = Show()
new_Show.title=show_form.cleaned_data['title']
new_Show.body=show_form.cleaned_data['body']
new_Show.pub_date=timezone.now()
new_Show.location=show_form.cleaned_data['location']
new_Show.time=show_form.cleaned_data['time']
new_Show.save()
if img_form.is_valid():
image=Image(image=request.FILES['imageFile'])
new_Show.image_set.add(image)
return HttpResponseRedirect(reverse('shows'))
else:
return HttpResponseRedirect(reverse('shows'))
else:
show_form = NewShowForm()
img_form = ImageForm()
return render_to_response(
'shows/new_show.html',
{'show_form': show_form, 'img_form': img_form},
context_instance=RequestContext(request)
)
Here is my template snippet:
<form action="{% url "new_show" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ show_form.non_field_errors }}</p>
<p>
<label for="title">Title:</label>
<input type="text" name="title"/>
</p>
<p>
<label for="body">Body:</label>
<textarea type="text" name="body"> </textarea>
</p>
<p>
<label for="location">Location:</label>
<input type="text" name="location"/>
</p>
<p>
<label for="time">Date:</label>
<input type="text" id="time" maxlength="25" size="25" name="time"><img src="{{ STATIC_URL }}../../static/cal.gif" width="16" height="16" border="0" alt="Pick a date">
</p>
<!-- Upload Form. Note enctype attribute! -->
{% csrf_token %}
<p>{{ img_form.non_field_errors }}</p>
<p>{{ img_form.imageFile.label_tag }}</p>
<p>
{{ img_form.imageFile.errors }}
{{ img_form.imageFile }}
</p>
<p><input type="submit" value="Add Upcoming Show"></input></p>
</form>
Here is my form Class:
class NewShowForm(forms.Form):
title=forms.CharField()
body=forms.CharField(widget=forms.TextArea)
location=forms.CharField()
time=forms.DateTimeField(required=True)
class ImageForm(forms.Form):
imageFile = forms.FileField(required=False, label='Select an Image')
Please help me!
If new_Show is a model, why not create a ModelForm instead of forms.Form?
So, instead of
class NewShowForm(forms.Form):
title=forms.CharField()
body=forms.CharField(widget=forms.TextArea)
location=forms.CharField()
time=forms.DateTimeField(required=True)
class ImageForm(forms.Form):
imageFile = forms.FileField(required=False, label='Select an Image')
why not using,
from django.forms import ModelForm
class NewShowForm(ModelForm):
class Meta:
model = NewShow
class ImageForm(ModelForm):
class Meta:
model = Image
?
Using ModelForm will ensure that form validation meets that of model. Moreover, it can cut off your code (especially line 6 to 11).
It will help to add these two lines to your view before if is_valid() to see the errors it's giving:
if request.method == 'POST':
img_form = ImageForm(request.POST, request.FILES)
show_form = NewShowForm(request.POST)
print(form.is_valid())
print(form.errors)
if show_form.is_valid():
You can paste the errors here and we can see what's the issue
Since you've put 2 Django forms together under one HTML form tag, when you submit the form on the front-end you're sending an extra field through request.POST that your NewShowForm doesn't have. If you combine both forms into a single Django form, you should be able to get this to work.
Related
Hi im trying to pass a name from a form to a view in django using POST. There are no errors in the execution but its passing nothing from the template and dont know if i doing something wrong here. Im starting with django so i can have newbie errors. If u need more information tell me pls.
Views.py
def crear_pdf(request):
empresa_selec = ""
form = EmpModelForm()
if request.method == 'POST':
form = EmpModelForm(data=request.POST)
if form.is_valid():
empresa_selec = form.cleaned_data['nombre']
#"empresa_selec" that's the empty variable
Models.py
class Empresa_modelo(models.Model):
nombre = models.CharField(max_length=100,blank=True,null=True)
Forms.py
class EmpModelForm(forms.ModelForm):
class Meta:
model = Empresa_modelo
fields = ["nombre"]
template.html
<div class="container-fluid">
<form method="POST" enctype="multipart/form-data" action="{% url 'crear_pdf' %}">{% csrf_token %}
<p>Empresa</p>
<input type="text" name="empresa">
<br>
<button type="submit">Subir</button>
</form>
<br>
<a class="btn btn-primary" href="{% url 'crear_pdf' %}">Atras</a>
</div>
You haven't got a field called nombre in your template; you only have empresa.
That's presumably because you don't ouput your EmpModelForm in the template. You don't show your render call in the view, but assuming you pass it as form, you should just do {{ form.as_p }} in the template.
Try using:
<input type="text" name="nombre">
There is no field named empresa.
Had a look at your code,there are a couple of issues.First you are not using the model form defined in your forms.py file in your template. Second you have defined an input text box with the name that you are not referring in your views. Either use the model form or use the same name of your input text box in your views.
def crear_pdf(request):
empresa_selec = ""
form = EmpModelForm()
if request.method == 'POST':
form = EmpModelForm(data=request.POST)
if form.is_valid():
empresa_selec = form.cleaned_data['nombre']
else:
return render(request,"template.html",{"form":form})
And in your template you can edit as such:
<div class="container-fluid">
<form method="POST" enctype="multipart/form-data" action="{% url 'crear_pdf' %}">{% csrf_token %}
{{ form.as_p }}
<br>
<button type="submit">Subir</button>
</form>
<br>
<a class="btn btn-primary" href="{% url 'crear_pdf' %}">Atras</a>
</div>
Hope this helps.
I've got a feedback app in django and it all seems to work fine, no errors i can submit the form and it all seems to work, however i have my model registered into my admin however when i submit the form i doesn't appear in my admin. Sorry if this is very basic i just cant get my head around it please help.
in my models.py
class Feedback(models.Model):
email = models.CharField(max_length=100)
message = models.CharField(max_length=1000)
def __unicode__(self):
return self.title
which i then pass through to forms.py
class FeedbackModelForm(forms.ModelForm):
class Meta:
model = Feedback
fields = ["email", "message"]
and my view is
def feedbackform(request):
form = FeedbackModelForm(request.Post or None)
if form.is_valid():
form.save()
return render(request, "feedback.html", {"form": form})
now in my html looks like this
{% block content %}
<div id="feedback">
<div id="feedback-form" style='display:none;' class="col-xs-4 col-md-4 panel panel-default">
<form method="POST" action="{{ form }}" class="form panel-body" role="form">{% csrf_token %}
<div class="form-group">
<input class="form-control" name="email" autofocus placeholder="Your e-mail" type="email" />
</div>
<div class="form-group">
<textarea class="form-control" name="message" required placeholder="Please write your feedback here..." rows="5"></textarea>
</div>
<button class="btn btn-primary pull-right" type="submit">Send</button>
</form>
</div>
<div id="feedback-tab">Feedback</div>
</div>
{% endblock %}
and in my admin
from .models import Feedback
from .forms import FeedbackModelForm
class FeedbackAdmin(admin.ModelAdmin):
form = FeedbackModelForm
admin.site.register(Feedback, FeedbackAdmin)
You have passed the
{{ form }}
as the action attribute, which is completely wrong. Put it inside a div as
{{ form.as_p }}
that will work for you.
And in the action attribute pass a url in the form of
{% url 'home_page_example' %}
if you wanted to remain in the same page and redirect via view
you can write
action = "."
Show us how did you register your model in the admin.
Make sure that you explicit config the form, like this
class FeedbackAdmin(admin.ModelAdmin)
form = FeedbackModelForm
admin.site.register(Feedback, FeedbackAdmin)
You should return email or message in def __unicode__(self):, not title.
class Feedback(models.Model):
email = models.CharField(max_length=100)
message = models.CharField(max_length=1000)
def __unicode__(self):
return self.email
I think that you should check if the view is currently saving your Feedback.
Try inspecting the DB or in a manage.py shell check if len(Feedback.objects.all()) change when you submit a Feedback in your view.
Also, I recommend you to change the email field to an EmailField and use the FormView class based view.
I recently tried the forms validations and faced an issue with ValidationError().
The form error does not appear in my website when I submit the form.
Here is the code:
forms.py
class ArticleForm(forms.ModelForm):
def clean_titre(self):
titre = self.cleaned_data['titre']
if len(titre) < 5:
raise ValidationError('myError')
return titre
form = ArticleForm()
template.html
<div class="form-group">TITRE
{{ form.titre.errors }}
{{ form.titre }}
</div>
views.py
def AddArticle(request):
form = ArticleForm(request.POST, request.FILES)
if form.is_valid():
save_it = form.save(commit=False)
save_it.user = request.user
save_it.save()
form.save_m2m()
return HttpResponseRedirect('/')
What did I do wrong?
--- EDIT ---
Full template.html
<form class="form" action="{% url "article.views.AddArticle" %}" method="post" enctype='multipart/form-data'>
{% csrf_token %}
<div class="form-group">TITRE
{{ form.titre.errors }}
{{ form.titre }}
</div>
<div class="form-group">SUMMARY
{{ form.media }}
{{ form.summary.errors }}
{{ form.summary }}
</div>
<div class="form-group">CONTENU
{{ form.media }}
{{ form.contenu.errors }}
{{ form.contenu }}
</div>
<div class="form-group">
{{ form.image.errors }}
{{ form.image }}
</div>
<div class="form-group">TAGS
{{ form.tags.errors }}
{{ form.tags }}
</div>
<input type="submit" class="btn btn-default" value="Submit" autocomplete="off" autocorrect="off" />
</form>
I'll post the full forms.py too, it may help.
forms.py
class ArticleForm(forms.ModelForm):
def clean_titre(self):
titre = self.cleaned_data['titre']
if len(titre) < 5:
raise ValidationError('myError')
return titre
class Meta:
model = Article
exclude = ['date', 'rating', 'user']
widgets={
"titre":forms.TextInput(attrs={'placeholder':'Le titre', 'class':'form-control'}),
"contenu":forms.Textarea(attrs={'placeholder':'Le Contenu de votre message', 'class':'form-control'}),
"image":forms.FileInput(attrs={'placeholder':'Votre Image', 'id':'uploadBtn'}),
"tags":TagWidget(attrs={'placeholder':'Vos Tags', 'class':'form-control'}),
}
form = ArticleForm()
You are missing the else portion within your view. Here is the general flow of what forms usually do:
Users navigate to a page via GET which presents them with a form
Users fill in the form and submit it by using POST
If the form is valid, users are directed to a different page
If the form is not valid, users are presented with the same page as in step 1 with the validation errors displayed. After users correct them, they are process to step 2.
Here is that flow in django view:
def AddArticle(request):
if request.method == 'POST':
form = ArticleForm(request.POST, request.FILES)
if form.is_valid():
save_it = form.save(commit=False)
save_it.user = request.user
save_it.save()
form.save_m2m()
return HttpResponseRedirect('/')
else:
form = ArticleForm()
return render(request, 'template.html', {'form': form'})
I would however look into using class based views in Django. Initially they can seem very confusing but over time you will learn to appreciate them. Docs. Another useful resource when learning CBV.
By using CBV, the above can be simplified to:
class AddArticleView(CreateView):
success_url = 'name_of_view_here'
form_class = ArticleForm
template_name = 'template.html'
# urls.py
urlpatterns = patterns('', url(r'^articles/add/$', AddArticleView.as_view()))
Template
You also need to include the overall form error in the template, in addition to each field errors:
<form class="form" action="{% url "article.views.AddArticle" %}" method="post" enctype='multipart/form-data'>
{% csrf_token %}
{{ form.non_field_errors }}
...
</form>
Please note that you might need to wrap the errors with some bootstrap markup. More info in docs
i am not able to upload an image from html page but it is possible from admin page
here is my models.py:
def get_upload_file_name(instance,filename):
return "image/%s_%s"%(str(time()).replace('.','_'),filename)
class Company_Profile(models.Model):
user = models.ForeignKey(User)
name = models.CharField(_('Company Name'), max_length= 30)
logo = models.FileField(_('Company Logo'), upload_to=get_upload_file_name)
address = models.TextField(_('Contact Address'), max_length=50)
phone_no = models.IntegerField(_('Contact No'), max_length=12)
my views.py:
def company_prof(request):
if request.method == 'POST':
comp_prof = Company_Prof(request.POST, request.FILES)
if comp_prof.is_valid():
save_prof = comp_prof.save(commit=False)
save_prof.user = request.user
save_prof.save()
messages.success(request, 'Thank you for Registration')
return HttpResponseRedirect('company/'+str(save_prof.id))
else:
comp_prof =Company_Prof()
variables = RequestContext(request, {
'comp_form': Company_Prof()})
return render_to_response("comp_profile.html",
locals(),
context_instance = RequestContext(request))
my settings.py is:
MEDIA_ROOT ='G:\Mini project\Pycharm projects\project4\static/'
MEDIA_URL = ''
html page is:
<form enctype="application/x-www-form-urlencoded" class="global_form" action="" method="post"><div><div><h3>Create Account</h3>
<div id="connect_signup_box" class="connect_box_form clearfix">
<form method="POST" enctype="multipart/form-data">{% csrf_token %}
{{ comp_prof.as_p }}
<input type="submit" class="btn btn-success" value="submit">
{% if save_prof %}
<h3>The details are submitted</h3>
{% endif %}
<input type="reset" class="btn" value="cancel">
{% if value == 'cancel' %}
<h3>Canceled</h3>
{% endif %}
</form>
</div>
</div>
</div>
</form>
when i submit it says no files are chosen. but from admin page there is no problem.
help me..
I think the problem is you have nested forms, which isn't supported by browsers (Can you nest html forms?).
So I am assuming that the browser is just using the first form definition, which has the wrong enctype. Try removing the first form declaration and just keeping this one: <form method="POST" enctype="multipart/form-data">.
I'm working on a model formset for a Membership model (models auth.User membership to app.Project). Here's app/forms.py, after I trimming things I have confirmed to be irrelevant after commenting them out:
class EditMembership(forms.ModelForm):
delete = forms.BooleanField(required=False, initial=False)
class Meta:
model = models.Membership
fields = ('is_owner',)
def clean_delete(self):
return self.cleaned_data['delete']
class BaseEditMemberships(forms.models.BaseModelFormSet):
# Some custom methods not dealing with validation.
pass
EditMembershipSet = forms.models.modelformset_factory(models.Membership,
form=EditMembership, extra=0, formset=BaseEditMemberships)
Here is my template:
<form method="{{ method|default:"post" }}" action="{{ action }}">
{% csrf_token %}
<ul>
{% for form in formset %}
<li>{{ form.instance.user}}</li>
{{ form.as_ul }}
{% endfor %}
</ul>
<input type="submit" value="{{ submit_value|default:"Submit" }}" />
</form>
And my view:
#ownership_required(message="You must be an owner to edit memberships.")
def edit_memberships(request, pk):
project = get_object_or_404(models.Project, pk=pk)
if request.method == "GET":
formset = forms.EditMembershipSet(
queryset=project.membership_set.all()
)
return render_formset_fullpage(request, formset, "Edit Memberships",
template=forms.EDITMEMBERSHIPS_PATH)
elif request.method == "POST":
formset = forms.EditMembershipSet(request.POST)
return HttpResponse("Hooray!")
And the model in question:
class Membership(models.Model):
class Meta:
unique_together = ('project', 'user')
project = models.ForeignKey('common.Project', editable=False)
user = models.ForeignKey('auth.User')
is_owner = models.BooleanField(default=False, blank=False,
help_text="Indicates ownership of the project")
project_alias = models.CharField(max_length=CHARFIELD_SHORT,
help_text="User-given name", blank=True)
The problem is I keep getting a ValidationError back after doing the POST:
ValidationError at /project/4/memberships
[u'ManagementForm data is missing or has been tampered with']
From what I can tell, forms.EditMembership is doing OK. I can render that form and recreate it from the POST with no validation error, so I guess it is something wrong with the way I am using BaseEditMemberships/EditMembershipSet.
EDIT:
Just to give you even more information, here are an example form which is generated and the POST vars for one of my test requests. The form:
<form method="post" action="">
<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='d6d535efd35e83076e1ac14a82ef4cdc' /></div>
<ul>
<li>someuser</li>
<li><label for="id_form-0-is_owner">Is owner:</label>
<input checked="checked" type="checkbox" name="form-0-is_owner" id="id_form-0-is_owner" />
</li>
<li><label for="id_form-0-delete">Delete:</label>
<input type="checkbox" name="form-0-delete" id="id_form-0-delete" />
<input type="hidden" name="form-0-id" value="8" id="id_form-0-id" />
</li>
</ul>
<input type="submit" value="Submit" />
</form>
Corresponding POST vars if I check the delete box:
form-0-id: u'8'
csrfmiddlewaretoken: u'd6d535efd35e83076e1ac14a82ef4cdc'
form-0-delete: u'on'
form-0-is_owner: u'on'
You need to include {{ formset.management_form }} in your template. See Django's formset documentation on rendering templates for formsets.