can not find the error: Page not found (404) - django-forms

Showing following error:
Page not found (404)
Request Method: POST
Request URL: http://127.0.0.1:8000/events/toggle-attendance/%3E%3Cinput%20type=
Using the URLconf defined in std.urls, Django tried these URL patterns, in this order:
^events/ ^tonight/$ [name='ev_tonight']
^events/ ^create/$ [name='ev_create']
^events/ ^toggle-attendance/$ [name='ev_toggle_attendance']
^admin/
The current URL, events/toggle-attendance/><input type=, didn't match any of these.
Template:
<form method="POST" class="toggle_attendance_form" action="{% url ev_toggle_attendance %}>
<input type="hidden" name="event_id" value="{{ event.id }}" />
{% if attending %}
<input class="attendance unattend" type="submit" value="Unattend" />
{% else %}
<input class="attendance attend" type="submit" value="Attend" />
{% endif %}
</form>
View:
def toggle_attendance(request):
try:
# going to assume values in the post parameter
event_id = int(request.POST['event_id'])
# couple of possible errors: no event_id in POST parameter or value can not casted as int
except (KeyError, ValueError):
# raising http404: means it couldnt be found
raise Http404
# getting the event where id= event_id
event = get_object_or_404(Event, id=event_id)
#
attendance, created = Attendance.objects.get_or_create(user=request.user,
event=event)
if created:
pass
# messages.add_message(request, messages.INFO, 'You are now attending %s.' % event)
else:
attendance.delete()
# messages.add_message(request, messages.INFO, 'You are no longer attending %s.' % event)
# Check to see whether the next variable in the POST parameters
next = request.POST.get('next', '')
if not next:
next = reverse('ev_tonight')
return HttpResponseRedirect(next)
toggle_attendance = login_required(toggle_attendance)
url:
urlpatterns = patterns('',
url(r'^tonight/$', views.tonight, name='ev_tonight'),
url(r'^create/$', views.create, name='ev_create'),
url(r'^toggle-attendance/$', views.toggle_attendance, name='ev_toggle_attendance'),
)
can you please help me finding the error?

Found it! You are missing a close quote at
<form method="POST"
class="toggle_attendance_form" action="{% url ev_toggle_attendance %}>
Which should be
<form method="POST"
class="toggle_attendance_form" action="{% url ev_toggle_attendance %}">
Hope that solve it!

Related

How to set each field as required for formset_factory in Django (how to validate blank forms in formsets)

I have the form in my forms.py:
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
age = forms.CharField(label='Age', max_length=100)
sex = forms.CharField(label='Sex', max_length=100)
I created the formset_factory
NameFormSet = formset_factory(NameForm, extra=0)
In my views.py for the get context_data, I have:
...
def get_context_data(self, **kwargs):
context = super(APView, self).get_context_data(**kwargs)
if self.request.POST:
context['formset'] = NameFormSet()
else:
recommended = returnWebAttackResults(self.kwargs['webAttack'])
if recommended is None:
context['recommendedAP'] = False
else:
context['formset'] = NameFormSet(initial=recommended[0])
return context
....
In my template file, I have:
<form class="row" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors }}
{% for forma in formset.forms %}
{{ forma }}
{% endfor %}
<input class="btn bg-success" type="submit" value="Update" />
</form>
My problem is that I don't get "This field is required" when I click the "Update" button. I tried setting the use_required_attribute to True, but it did not work.
Scenario:
The returnWebAttackResults function gets the initial data for the forms in the formset. So, if I have three forms, if one of the fields is blank (no user input) in any of the forms, then when I click the Update button, each field that is blank should be highlighted with the "This field is required". I can do this when I just render a regular form, but when I am using formsets, it does not work.
Is there a way to validate the forms in the formset before the request in sent?
I hit the same problem and found this in the documentation
https://docs.djangoproject.com/en/3.0/ref/forms/fields/#core-field-arguments
Widgets of required form fields have the required HTML attribute. Set the Form.use_required_attribute attribute to False to disable it. The required attribute isn’t included on forms of formsets because the browser validation may not be correct when adding and deleting formsets.
If you have an empty row (for adding an extra record) then you can't save the form until the empty row is filled in. So, if you want to say update one existing row without adding an extra row then you have a problem, you can't do it. The problem really comes from the fact that a formset is really in html terms just a single form. A workaround for that problem might be to use javascript to add rows to the formset only as needed, as in this example:
https://whoisnicoleharris.com/2015/01/06/implementing-django-formsets.html
There is probably furthermore a javascript solution to validate the form fields before you send the request, I think this may be such a solution but I haven't tried it:
https://jqueryvalidation.org/required-method/
It would make sense that a completely empty row should not be validated for required fields but just ignored altogether.
UPDATE: I got a simple solution working from the example in the above link. My template looks like this (note that no empty row is shown initially thanks to the if statement):
{% extends "base_generic.html" %}
{% load static %}
{% block content %}
<h1>Experiment Detail</h1>
<form name="test_form" method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{% if form.name.value %}
<div class="link-formset">
{{ form.name }}
</div>
{% endif %}
{% endfor %}
<input type="submit" value="Save" class="button"/>
</form>
<!-- Include formset plugin - including jQuery dependency -->
<!-- <script src="{% static 'path_to/jquery-3.4.1.js' %}"></script> -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'js/jquery_formset.js' %}"></script>
<script>
$('.link-formset').formset({
addText: 'Add',
deleteText: 'Delete'
});
</script>
{% endblock %}
In my view I have this for loop to set the use_required_attribute:
for form in formSet:
form.use_required_attribute = True
The solution seems to work OK, when I click the Add button an empty row appears and the empty 'name' field has the expected red box round the empty field and when I try to click Save I get the message 'Please fill out this field.'
the solution is, add BaseFormSet in froms.py, like this:
forms.py
from django.form import BaseFormSet
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100, blank=False)
age = forms.CharField(label='Age', max_length=100, blank=False)
sex = forms.CharField(label='Sex', max_length=100, blank=False)
class RequiredFormSet(BaseFormSet):
def __init__(self, *args, **kwargs):
super(RequiredFormSet, self).__init__(*args, **kwargs)
for form in self.forms:
form.empty_permitted = False
form.use_required_attribute = True
NameFormSet = formset_factory(NameForm, formset=RequiredFormSet)

csrf token for ajax in django2

I am learning Django2,and try to make a login page with csrf_token and ajax.
I hope that if user hasn't lgoin,that will turn to the login page and send a variable next as a tag of the page before login.If user login successfully that I can turn to the homepage or page marked by next.
I read the docs of Django2, and try to code like below,however,when I click "LOGIN" button,it just refresh the login page and get no error
I am confused and have no idea already.Please help.
login views:
def login(request):
if request.is_ajax():
uf = UserForm(request.POST)
if uf.is_valid():
# get info from form
username = uf.cleaned_data['username']
password = uf.cleaned_data['password']
user = auth.authenticate(request, username=username, password=password)
if user is not None: # user match
auth.login(request, user)
if request.GET.get('next'):
next_url = request.GET.get('next')
return JsonResponse({'redirect_url': next_url})
# return redirect(request.GET.get('next'))
else:
return JsonResponse({'redirect_url': 'home'})
else: # user not match
error_msg = ["username or pwd mistake"]
return JsonResponse({'error_msg': error_msg})
else:
uf = UserForm()
return render(request, 'login.html', {'uf': uf})
html :
<form>
{% csrf_token %}
{{ uf.username }}
{{ uf.password }}
<div id="errorMsg"></div>
<button type="submit" class="btn btn-default" id="loginButton">login</button>
<input type="hidden" name="next" id="redirect-next" value="{{ next|escape }}"/>
</form>
JQuery:
$("#loginButton").click(function () {
$.ajax({
url: "",
type: 'POST',
dataType: "json",
data: {username: $("#inputEmail3").val(), password: $("#inputPassword3").val()},
beforeSend: function (xhr, settings) {
var csrftoken = Cookies.get('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
success: function (result) {
if (result.error_msg) {
$('#errorMsg').show().text('user info error') //print an alert on the page
}
else {
location.href = result.redirect_url //turn to homepage or page before login
}
}
})
});
You don't need to take effort to write a login view of your own like this. Django provides easier methods to implement it.
First make sure the following are included in your settings.py
MIDDLEWARE_CLASSES = [
...
'django.contrib.auth.middleware.AuthenticationMiddleware',
...
]
INSTALLED_APPS = [
...
'django.contrib.auth',
'django.contrib.contenttypes',
...
]
Add all the login URLs to your main urls.py:
from django.urls import path
from django.conf.urls import include
urlpatterns = [
....
path('accounts/', include('django.contrib.auth.urls')),
....
]
Don't forget to run python manage.py migrate to create the tables required for the auth app. Now that the app and URLs are ready, templates need to be created. All the templates for the app should be placed under a folder named registration under your templates directory. The directory structure should be something like.
your_django_app/
templates/
registration/
login.html
__init__.py
apps.py
settings.py
urls.py
views.py
wsgi.py
The contents of the login.html should be something like:
<form id="loginform" action="{% url 'login' %}" method="POST">
{% csrf_token %}
{% if next %}
<input type="hidden" name="next" value="{{ next }}" />
{% endif %}
<input name="username" id="id_username" type="text">
<label>Username</label>
<input name="password" id="id_password" type="password">
<label>Password</label>
{% if form.errors %}
Error! Wrong credentials.
{% endif %}
<button type="submit">Login</button>
</form>
After this include these in your settings.py file for redirecting users correctly after login.
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/accounts/login'
You are all set to go. Make sure to create at least one user before trying this out by running python manage.py createsuperuser. For all pages that require users to login before viewing them you can use the #login_required decorator above their respective view functions to redirect them to the login page before showing the page. Example:
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
#login_required
def home(request):
return render(request, 'home/index.html')
Here there is a short and simple way to parse the csrf_token using ajax:
Inside the script tag.
$.ajax({
url: window.location.pathname,
type: 'POST',
data: {
......,
// Note this step.
'csrfmiddlewaretoken': "{{ csrf_token }}"
},
success: function() {
.....
}
});
Hope things work well as I have used this thing to parse the csrf_token in my 2 Django based projects. Cheers!
This might be related to this issue
As your button tries to submit the form but you want it to be handled handled by the script.
try changing the button type to
type="button"

Django - Allow User to Edit Profile and then Show Updated Profile fields

I have the form populating with the user profile information, but when I click save, it doesn't actually update.
Any clues/hints as to which part I need to modify is greatly appreciated.
Thanks in advance!
views.py
def profile_view(request):
user = request.user
form = EditProfileForm(initial={'first_name':user.first_name, 'last_name':user.last_name})
context = {
"form": form
}
return render(request, 'profile.html', context)
def edit_profile(request):
user = request.user
form = EditProfileForm(request.POST or None, initial={'first_name':user.first_name, 'last_name':user.last_name})
if request.method == 'POST':
if form.is_valid():
user.first_name = request.POST['first_name']
user.last_name = request.POST['last_name']
user.save()
return HttpResponseRedirect('%s'%(reverse('profile')))
context = {
"form": form
}
return render(request, "edit_profile.html", context)
forms.py
class EditProfileForm(forms.ModelForm):
first_name = forms.CharField(label='First Name')
last_name = forms.CharField(label='Last Name')
class Meta:
model = User
fields = ['first_name', 'last_name']
edit_profile.html
{% extends "base_site.html" %}
{% block content %}
<h1>Edit Profile</h1>
<form method="POST" action="/accounts/profile/" class="" />
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
{% endblock %}
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^register/$', 'accounts.views.registration_view', name='auth_register'),
url(r'^login/$', 'accounts.views.login_view', name='auth_login'),
url(r'^logout/$', 'accounts.views.logout_view', name='auth_logout'),
url(r'^profile/$', 'accounts.views.profile_view', name='profile'),
url(r'^profile/edit/$', 'accounts.views.edit_profile', name='edit_profile'),
]
The action in your form is POSTing to profile_view and not edit_profile and your forms are self closing so they aren't being POSTed correctly.
Change this:
<form method="POST" action="/accounts/profile/" class="" />
To this:
<form method="POST" action="/accounts/profile/edit" class="" >
Or even better, use the django url template tag:
<form method="POST" action="{% url 'edit_profile' %}" class="" >

how to do ajax or jquery with django1.3

I am absolutely new to django framework and new to web development and python. Currently I'm trying to implement ajax in my project. I am not able to find any working sample. I need help with putting ajax or jquery in a django1.3 project.
Now I'm trying to implement ajax using dojango' app. I install it successfully and trying this tutorial.
urls.py:
(r'^dojango/', include('dojango.urls')),
(r'^simple/', 'views.simple'),
(r'^simple-ajax-set/', 'views.simple_ajax_set'),
views.py:
from django.shortcuts import render_to_response
from dojango.decorators import json_response
#expect_post_request
#json_response
def simple_ajax_set(request):
ret = {}
firstname = request.POST['firstname']
surname = request.POST['surname']
if len(surname)<3:
ret['error'] = 'Surname is too short.'
ret['success'] = False
if ret['success']:
# Store the data here
pass
return ret
simple.html
{% extends "dojango/base.html" %}
{% block dojango_page_title %}Simple AJAX with dojango{% endblock %}
{% block dojango_header_extra %}
<script type="text/javascript">
function userFormSubmit(){
var form = dojo.byId("userForm");
dojo.xhrPost({url:form.action,
handleAs:"json",
content:{surname:form.surname.value,
firstname:form.firstname.value
},
load:function(response, ioArgs){
if (response.success){
dojo.byId("info").innerHTML = "Submitted successfully";
} else {
dojo.byId("info").innerHTML = "Error: "+response.error;
}
},
error:function(data){ // This happens on a 500 error or alikes.
dojo.byId("info").innerHTML = "Error sending data.";
}
});
}
</script>
{% endblock %}
{% block dojango_content %}
<form id="userForm" onsubmit="userFormSubmit(); return false;" action="/simple-ajax-set/">
First name: <input id="firstname" /><br />
Surname: <input id="surname" /><br />
<input type="submit" value="Submit" /> <span id="info"></span>
</form>
{% endblock %}
When I run I got the exception
NameError at /simple-ajax-set/
name 'expect_post_request' is not defined
So I change my code as in the first part of the above tutorial, and I got the following exception
'MultiValueDictKeyError at /simple-ajax-set/' , "Key 'firstname' not found in <QueryDict: {}>" when click on the submit button at simple.html.
Please help me to find out the problem sand also share some links or codes containg ajax/jquery which works with django1.3. and python 2.7,
Can any one suggest working a hello world ajax or jquery example for django1.3?
"Pure" jQuery and django here. That made me happy when i was on your place. Good luck!

Django, form valid question

I have 3 forms at the same page and each has a different form submit. Such as:
<h1>Address</h1>
<form method="post" id="adress_form" action=/profile/update/>
{{ form_address.as_p }}
<p><button type="submit">Save</button></p>
</form>
<h1>Email Change</h1>
<form method="post" id="email_form" action=/profile/update/>
{{ form_email.as_p }}
<p><button type="submit">Save</button> </p>
</form>
<h1>Password Change</h1>
<form method="post" id="password_form" action=/profile/update/>
{{ form_password.as_p }}
<p><button type="submit">Save</button></p>
</form>
For the sake of simplicity, I didn't include the ajax post scripts, but each submit will be queried via ajax.
Now I want to do processing all at the same page, /profile/update/
For this I have to check which form is posted. If posted and valid give some response, if not give another response.
#login_required
def profile_update_view(request):
if request.method == 'POST' and request.is_ajax()::
user = request.user
form_adress = AdressForm(request.POST)
form_email = EmailForm(request.POST)
form_password = PasswordChangeForm(request.POST)
if <CHECK IF THE SUBMIT IS AN ADDRESS FORM>
if form_adress.is_valid():
#update and return a json response object with "adress updated successfully." for ajax
else:
answer = {'answer': "Couldn't update. Your form is not valid"}
return HttpResponse(simplejson.dumps(answer), mimetype="application/json")
if <CHECK IF THE SUBMIT IS AN EMAIL FORM>
if form_email.is_valid():
#update and return a json response object with "email updated successfully." for ajax
else:
answer = {'answer': "Couldn't update. Your form is not valid"}
return HttpResponse(simplejson.dumps(answer), mimetype="application/json")
if <CHECK IF THE SUBMIT IS AN PASSWORD FORM>
if form_password.is_valid():
#update and return a json response object with "password changed successfully." for ajax
else:
answer = {'answer': "Couldn't update. Your form is not valid"}
return HttpResponse(simplejson.dumps(answer), mimetype="application/json")
else:
return HttpResponse(u"ONLY AJAX QUERIES PLEASE", mimetype="text/plain", status=403)
I somehow need to find out what form is posted.
How can I do this ?
Couldn't you just put a hidden input in each form w/ an identifier, and then just check for that in your view?
<h1>Address</h1>
<form method="post" id="adress_form" action=/profile/update/>
<input type="hidden" name="_address" />
{{ form_address.as_p }}
<p><button type="submit">Save</button></p>
</form>
and then in the view:
if '_address' in request.POST:
if form_adress.is_valid():
...

Resources