I'm trying to create a form. Here is my form class:
class RegisterForm(forms.Form):
login=forms.CharField(min_length=5,max_length=15)
password=forms.CharField(min_length=5,max_length=15,widget=forms.PasswordInput)
passwordConfirmation=forms.CharField(min_length=5,max_length=15,label="Re enter password",widget=forms.PasswordInput)
email=forms.EmailField(min_length=5,max_length=20)
question=forms.CharField(min_length=8,max_length=20,label="Security question")
answer=forms.CharField(min_length=5,max_length=20,widget=forms.PasswordInput)
answerConfirmation=forms.CharField(min_length=5,max_length=20,label="Re enter answer",widget=forms.PasswordInput)'
And now i have tamplate as follow:
{% if form.login.errors %}
{{ form.login.errors }}
{% endif %}
{{ form.login }}<label for="login">Enter desired login</label><br />
And so on i just only change form.name etc. to one from the forms class.
And when i filled form incorrect i don't get any error or nothing just blank form. Where I made a mistake? Thx for help
Edit:
Sorry i forget to show my function here is it
def register(request):
if request.method == 'POST':
form=RegisterForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/thanks/register')
else:
form = RegisterForm(auto_id=False)
return render_to_response('misc/register.html',locals(),context_instance=RequestContext(request))
else:
form=RegisterForm(auto_id=False)
return render_to_response('misc/register.html',locals(),context_instance=RequestContext(request))
form = RegisterForm(auto_id=False)
On this line you are creating new blank form and all validation errors are lost. Comment it out.
You've redeclared the form in the first else clause, so you've overwritten the errors. Drop that else clause completely, bring the very last line back one indent, so it catches the case when the firm is not valid.
Related
I have two Model Forms, one for notification types and one for privacy settings. Both show the defaults and not what is saved in the database. How can I make the form show the choice that's stored in the database instead of the defaults? Example: Say the user chose a Direct Message privacy of "Friends and Followers". When they visit the privacy options page again after having saved the changes, it shows "Open" instead of reflecting what is in the database. I tried assigning the values saved in the database directly to the form when rendering the page when the request is GET but that didn't do anything, even though the debug print shows that the value of form.dm_privacy is indeed what's in the database, it still shows "Open".
Both forms work fine, the changes get saved and everything. I don't understand why it's not reflecting the changes though, is this just something that Model Forms do and not something I can change?
privacy_options.html
{% extends "accbase.html" %}
{% block content %}
<h1>Privacy Options</h1>
<form method="post">
{% csrf_token %}
{{form.as_p}}
<button type="submit">Save</button>
</form>
{% endblock %}
views.py
#login_required
def privacy_options(request):
"""
Holds all privacy options such as.. open/closed DMs, who can see profile/posts on profile
"""
if request.method == "POST":
form = PrivacyOptionForm(request.POST)
if form.is_valid():
print("Before saving:",request.user.dm_privacy, request.user.profile_privacy, request.user.included_in_find_friends)
user = request.user.username
request.user.dm_privacy = form.cleaned_data['dm_privacy']
request.user.profile_privacy = form.cleaned_data['profile_privacy']
request.user.included_in_find_friends = form.cleaned_data['included_in_find_friends']
request.user.save()
print("After save:",request.user.dm_privacy, request.user.profile_privacy, request.user.included_in_find_friends)
return render(request, 'acc_manage/acc_nav.html', {'username':user})
else:
form = PrivacyOptionForm()
form.included_in_find_friends = request.user.included_in_find_friends
form.profile_privacy = request.user.profile_privacy
form.dm_privacy = request.user.dm_privacy
print("\n\n",form.dm_privacy, "\n\n")
return render(request, 'acc_manage/privacy_options.html', {'form': form})
Fixed it by changing form = PrivacyOptionForm() to form = PrivacyOptionForm(instance=request.user)
I'm using Django 1.5. I have a template with multiple forms: one driver has many cars (inline forms). I want to display a hint indicating which section contains errors.
The template:
{% if driver_form.is_bound and not driver_form.is_valid %}
Please correct errors in the Driver Data.
{% endif %}
{% if car_form.is_bound and not car_form.is_valid %}
Please correct errors in the Car Data.
{% endif %}
The problem is that if the first form is invalid, the second message pops up as well, even though the second form is valid. I also noticed that if I put {{ car_form.is_valid }} three times in a row, the first time it is empty, the next time (and following) it is True.
The original view:
if request.method == 'POST':
driver_form = DriverModelForm(request.POST)
car_form_set = CarInlineFormSet(request.POST) # wrong: no instance passed
if driver_form.is_valid():
driver = driver_form.save(commit=False)
car_form_set = CarInlineFormSet(request.POST, instance=driver)
if car_form_set.is_valid():
driver.save()
car_form_set.save()
else:
driver_form = DriverModelForm()
car_form_set = CarInlineFormset()
return render(request, 'template.html', {
'driver_form': driver_form,
'car_form_set': car_form_set
})
UPDATE:
It seems that for simplicity's sake I left out the details that actually caused the problem. Lesson learned.
There was a Javascript setting values on page load, while it only needed to be done on a dropdown change. It was hiding the erroneous values and causing the form to be valid next time around.
There is a dependency: driver_form is a model form, and car_form_set is an inline form set based on the instance that the driver_form is adding.
The problem was indeed in the view, as seddonym suggested: the car_form_set was not being initialized with an instance if the driver_form was invalid. So is_valid() was neither True nor False. Conclusion: using is_valid() in the template works just fine.
The fixed view:
driver = Driver()
if request.method == 'POST':
driver_form = DriverModelForm(request.POST, instance=driver)
if driver_form.is_valid():
driver = driver_form.save(commit=False)
car_form_set = CarInlineFormSet(request.POST, instance=driver)
if car_form_set.is_valid():
driver.save()
car_form_set.save()
else:
driver_form = DriverModelForm(instance=driver)
car_form_set = CarInlineFormset(instance=driver)
return render(request, 'template.html', {
'driver_form': driver_form,
'car_form_set': car_form_set
})
You don't need to call form.is_valid, that will already have been called by the view. Instead, check for errors:
{% if first_form.errors %}
Please correct errors in the First Form.
{% endif %}
{% if second_form.errors %}
Please correct errors in the Second Form.
{% endif %}
I have a simple form with a single text input field which is not getting displayed in the template.Only the form's submit button is displayed.
The template:
<form method='POST' action="example">
{{ form.as_p }}
<input type="submit" value="submit"/>
</form>
The form:
class sampleform(forms.Form):
data = forms.CharField(label = u'Add a text:')
The view:
def example(request):
if request.method == 'POST':
form = sampleform(request.POST)
if form.is_valid:
return HttpResponseRedirect('/register/success/')
else:
form = sampleform()
variables = RequestContext(request,{'form':form})
return render_to_response('stream.html',variables)
I also get such a bug, tried to change forms, at first I had a form.ModelForms, Then tried in new forms.Form, but it was still not out in template.
I win my bug when in View change Context {'form':form} to {'formZZZ':form} and template to {{ formZZZ }}, and 2 forms still work (Forms and ModelForms).
Question was 4 years ago, but hope it help for other, who take this result. Python 3.5, virtualenv on Win10, Django 1.11.1 Sorry for bad English.
I'm using the code found here (SO.com) to use the same template to both add and edit a record, but when I add a new record and click Submit, I get a 404 on the URL http://192.168.1.3:5678/app/student/edit/None/, and I'm not exactly sure why.
Here is the relevant portion of my urls.py:
url(r'^app/lesson/new/$', 'edit_lesson', {}, 'lesson_new'),
url(r'^app/lesson/edit/(?P<id>\d+)/$', 'edit_lesson', {}, 'lesson_edit'),
Here is the relevant portion of my views.py:
def edit_lesson(request, id=None, template_name='lesson_edit_template.html'):
if id:
t = "Edit"
lesson = get_object_or_404(Lesson, pk=id)
stu = get_object_or_404(Student, pk=sid)
if stu.teacher != request.user:
raise HttpResponseForbidden()
else:
t = "Add"
lesson = Lesson()
if request.POST:
form = LessonForm(request.POST, instance=lesson)
if form.is_valid():
form.save()
# If the save was successful, redirect to another page
return view_lessons(request)
else:
form = LessonForm(instance=lesson)
return render_to_response(template_name, {
'form': form,
't': t,
'lesson': lesson,
}, context_instance=RequestContext(request))
And finally, here is my template:
<h1>{{ t }} Lesson</h1>
<form action="/app/lesson/edit/{{ lesson.id }}/" method="post"> {% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
I'm certain that I'm missing something really easy, but I can't seem to put my finger on it. I'm using Django 1.3.1 if that makes any difference.
Thanks,
MC
There's no need to specify any URL in the form's action attribute. Just do
<form action="" method="post">
and it will POST back to the URL that you originally used to access it, which is what you want.
In add case {{ lesson.id }} is None, because lesson is unsaved Lesson() instance, without pk, so your form is being fired to nonexistent URL.
I recommend separating create and edit views and processing them in different ways (or even inherit generic views - with new class-based generic views it's easy and pleasant).
Also, use {% url %} template tag everywhere instead of hard-coded urls.
I have a model in Django that allows blanks for two date fields:
class ReleaseStream(models.Model):
name = models.CharField(max_length=200,db_column='name')
version = models.CharField(max_length=20,blank=True,db_column='version')
target_date = models.DateTimeField(null=True,blank=True,db_column='target_date')
actual_date = models.DateTimeField(null=True,blank=True,db_column='actual_date')
description = models.TextField(db_column='description')
...and a form definition:
class ReleaseStreamForm(ModelForm):
class Meta:
model = ReleaseStream
When the form comes up, I can fill in a value for the "target_date", and not for the "actual_date" fields, and when the form.save() fires it appears to write the value supplied for "target_date" into both fields. I have looked at the post data going into the code that does the form.save() and it definitely has a value for "target_date" and a '' for "actual_date", so I don't think that there is something weird with the form itself, variable names in the POST, etc.
Now, if I supply a non-blank value for "actual_date", the form.save() does the right thing - both the "target_date" and "actual_date" have the correct values written in. Am I doing something wrong, or is this potentially a bug in django?
Here is the template (sorry for the blank comment below:)
{% extends "base.html" %}
{% block title %}{{ form_title }}{% endblock %}
{% block subtitle %}{% endblock %}
{% block content %}
<form action={{ action_url }} method="post">
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit" />
</form>
{% endblock %}
And the code that handles the form:
def edit_release_stream(request,req_release_stream_id=None):
form_title = 'Edit release stream'
if request.method == 'POST':
if req_release_stream_id!=None:
release_stream_entry=ReleaseStream.objects.get(pk=req_release_stream_id)
form = ReleaseStreamForm(request.POST,instance=release_stream_entry)
else:
form = ReleaseStreamForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/releases/')
elif req_release_stream_id!=None:
release_stream_entry=ReleaseStream.objects.get(pk=req_release_stream_id)
form = ReleaseStreamForm(instance=release_stream_entry)
else:
form_title = 'Add new release stream'
form = ReleaseStreamForm()
return render_to_response('dashboard/tableform.html', {
'action_url': request.get_full_path(),
'form_title': form_title,
'form': form,
})
... And the post data coming in:
<QueryDict: {u'name': [u'NewRelease'], u'target_date': [u'2011-06-15 00:00'], u'version': [u'4.5.1'], u'actual_date': [u''], u'description': [u'']}>
You can see that it has a valid POST var of "actual_date", with an empty string. This post yields a form.save() that stores the string provided above for "target_date" for both "target_date" and "actual_date".
If I then run a post with differing values for the two dates - here is the post:
<QueryDict: {u'name': [u'NewRelease'], u'target_date': [u'2011-06-15 00:00'], u'version': [u'4.5.1'], u'actual_date': [u'2011-07-15 00:00'], u'description': [u'']}>
In this case, with two distinct, non-empty strings, it writes the correct value shown in the POST above into each of the fields in the db.
I don't believe it to be a bug in Django, or somebody would have seen this problem a long time ago. Can you show us the template that renders the form? Also, if you can show the contents of the request.POST, that'd also be useful.
I'm guessing that your template code is incorrect somehow. The only other problem I can think of would be custom validation in your form (if there is any). Is that the whole ModelForm definition that you've supplied?