I am trying to save a form to update an existing user, but I am unable to get it to work. The error occurs when I try to save the form. The console shows the error occurs in the view (internal server error).
Form:
class updateFirstName(forms.ModelForm):
class Meta:
model = User
fields = ('first_name',)
def __init__(self, *args, **kwargs):
super(updateInfoForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_id = 'id-updateFirst'
self.helper.form_class = 'blueForms'
self.helper.form_method = 'post'
self.helper.form_action = '/login/userInfoChange/'
self.helper.add_input(Submit('submit', 'Submit'))
view:
#json_view
#csrf_exempt
def userInfoChange(request):
context = RequestContext(request)
if request.method == 'POST':
user = User.objects.get(username=request.user.username)
user_form = updateFirstName(request.POST)
print user_form
if user_form.is_valid():
user_form.save()
print "Valid Form"
return {'success': True}
html:
<form id="updateUsername">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-success" type="button" id="submit-username">Change</button>
</span>
<input type="text" class="form-control" id="id_firstname" placeholder="First Name: {{user.first_name}}">
<script type="text/javascript">
$('#submit-username').click(function(){
$.ajax({//begin
type: 'POST',
url: '/login/userInfoChange/',
data: $('#updateUsername').serialize(),
success: function(result){
console.log('updateUsername');
}
});
});
</script>
</div><br></form>
Model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
confirmation_code = models.CharField(max_length=128)
reset_code = models.CharField(max_length=128)
address_lineOne = models.CharField(max_length=128)
address_lineTwo = models.CharField(max_length=128)
city = models.CharField(max_length=128)
State = models.CharField(max_length=128)
zipCode = models.CharField(max_length=10)
def __unicode__(self):
return self.user.username
Solution:
first_name = request.POST.get('first_name')
user.first_name = first_name
user.save()
Thanks ejey for resolving my csrf ajax issue.
If you are intending on posting using ajax you ought to use have a view method such as:
def some_ajax_view(request):
data = request.POST.copy()
if request.is_ajax() and request.POST:
...
...
You can get more information on how to process your ajax request without having to compromise on the csrf https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
Firstly, you didn't answer my question about the error message. This is a vital step in debugging, and it's very little use coming onto SO and asking questions without first finding the actual error and doing what you can to fix it yourself.
That said, you do have a huge obvious bug in your code. If the request is not a POST, and/or the form is not valid, what are you expecting to happen? Currently, your code just stops; so in either of those cases it will return None, which is an error: all views must return an HttpResponse. If you did look at the error message, that is probably what it would say.
You should ensure that your view at least returns an empty HttpResponse in either of those circumstances. More useful, though, would be a response that actually contains the errors from the form validation.
Related
Something very strange is happening, I've built a MultipleChoiceField in forms.py that is rendering as a normal list. I am unable to have the checkboxes display. I'm hoping someone can spot where I might have gone wrong.
forms.py
from django import forms
from . import models
from behaviour.models import Interventions
class IncidentForm(forms.Form):
def __init__(self,*args,**kwargs):
self.request = kwargs.pop('request')
super(IncidentForm,self).__init__(*args, **kwargs)
intervention_set = Interventions.objects.filter(schoolid_id = self.request)
intervention_choice = []
for intervention in intervention_set:
intervention_choice.append((intervention.pk, intervention.name))
self.fields['intervention'].choices = intervention_choice
intervention = forms.MultipleChoiceField(label='Intervention', choices=(), widget=forms.CheckboxSelectMultiple(), required=True,)
incident.html
<div>
<label class="control-label">{% trans 'Intervention' %}</label><br />
{{ form.intervention }}
<small class="form-control-feedback"> {{ form.intervention.errors }} </small>
</div>
HTML output
<div>
<label class="control-label">Intervention</label><br>
<ul id="id_intervention">
<li><label for="id_intervention_0"><input type="checkbox" name="intervention" value="3" id="id_intervention_0">
Communicate verbally with Parent</label>
</li>
<li><label for="id_intervention_1"><input type="checkbox" name="intervention" value="2" id="id_intervention_1">
Non-verbal signal</label>
</li>
<li><label for="id_intervention_2"><input type="checkbox" name="intervention" value="1" id="id_intervention_2">
Spoke with Student</label>
</li>
</ul>
<small class="form-control-feedback"> </small>
</div>
Screenshot of output
If you are using Django admin and you parent model is not using any relationship with child model but has charfield to store ids of selected items of child model that will be added to ModelAdmin as custom field.
Follow steps:
STEP 1: model.py
class yourparentmodel(models.Model):
...
prior_learning_checks = models.CharField(max_length=120, null = True, blank=True)
...
class childmodel(models.Model):
rpl_id = models.CharField(max_length=4, null = True, blank=True)
rpl_desc = models.CharField(max_length=120, null = True, blank=True)
Here in this example parent is CohortDetails as inline to Cohort, or can limit to Cohort only if don't need inlines.
and child model is StudentRPL here in this example.
STEP 2: admin.py
Add CheckboxSelectMultiple to list your table data that id and description in this example.
Then use init attach your custom field for child model with parent form.
class StudentRPLForm(forms.ModelForm):
student_prior_learning = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple(), queryset=StudentRpl.objects.all())
class Meta:
model = StudentRpl
fields = [
'rpl_indicator',
'rpl_description',
]
def __init__(self, *args, **kwargs):
super(StudentRPLForm, self).__init__(*args, **kwargs)
if self.instance and self.instance.pk:
self.fields['student_prior_learning']=forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple(), queryset=StudentRpl.objects.all())
rpl_list = []
ids = self.instance.prior_learning_checks
if ',' in ids:
ids = ids[0:(len(ids) - 1)]
rpl_list = ids.rsplit(',')
self.fields['student_prior_learning'].initial = StudentRpl.objects.filter(rpl_indicator__in=rpl_list)
Now it is time to save data by overriding save(self, commit).
Make sure use the cleaned_data. this is magic to collect only checked rows data and save to charfield of your parentmodel to read it again when to load the change_form. Because you are saving as comma separared ids, you have chance to load this string into list and filter your custom child model.
Other magic to view last saved ids in commas by assigning:
self.fields['student_prior_learning'].initial value to your filtered data in init function above (as i did)!!!
def save(self, commit=True, *args, **kwargs):
m = super(StudentRPLForm, self).save(commit=False, *args, **kwargs)
selected_rpl_list = ''
if self is not 'CohortDetailsForm':
for cr in self.cleaned_data['student_prior_learning']:
selected_rpl_list += cr.rpl_indicator + ','
m.prior_learning_checks = selected_rpl_list
if commit:
m.save()
STEP 3: admin.py
Assign your form to Inline or directly to modeladmin class if you don't need inlines.
class CohortDetailInline(admin.StackedInline):
model = CohortDetails
form = StudentRPLForm
fieldsets = ['fields':, ('student_prior_learning')]
.....
#admin.register(Cohort)
class CohortAdmin(admin.ModelAdmin):
inlines = CohortDetailInline
....
DONE !!!!
I am using a to handle a login. In the case of incorrect credentials, I use Ajax to print an error message on the same web page but in the case of success I would like to forward to another web page. What is happening is that even in the case of success it is printing results on the same page. I know that this has partially to do with the fact that you can't send a redirect to Ajax. However, still a newbie to know how to go about it. Any suggestions?
Here is my gsp section having to do with this form:
<g:formRemote name="subForm" url="[controller:'admin', action:'authenticate']" update = "error_message">
<br><br><label>User Name (email): </label><g:textField name = "username" /><br><br>
<label>Password: </label><g:field name = "password" type = "password" /><br><br><br><br>
<div id = "error_message" style = "text-align: center"> </div>
<div style = "text-align: center">(for TWC employees only)</div>
<g:submitButton id = "submit_button" name="Submit"/>
</g:formRemote>
and here is the controller method 'authenticate':
def authenticate = {
try {
MongoClient mongoClient = new MongoClient("localhost", 27017)
DB db = mongoClient.getDB("admin");
def userName = params.username
def passWord = params.password
boolean auth = db.authenticate(userName, passWord.toCharArray())
if (auth)
redirect (action: loggedin)
else {
render "Login or Password incorrect!"
}
}
catch (UnknownHostException e) {
e.printStackTrace();
}
catch (MongoException e) {
e.printStackTrace();
}
}
def displayerror = {
render "Login or Password incorrect!"
}
def loggedin = {}
As it is, I can't get the gsp corresponding to the 'loggedin' method to display. Any ideas?
Minor adjustments needed to previous poster's most helpful suggestions. This is the code that will actually solve the issue.
<g:formRemote name="subForm" url="[controller:'admin', action:'authenticate']" onSuccess="doResult(data)">
<br><br><label>User Name (email): </label><g:textField name = "username" /><br><br>
<label>Password: </label><g:field name = "password" type = "password" /><br><br><br><br>
<div id = "error_message" style = "text-align: center"> </div>
<div style = "text-align: center">(for TWC employees only)</div>
<g:submitButton id = "submit_button" name="Submit"/>
</g:formRemote>
javascript below:
function doResult(data) {
if (data.success == true) {
window.location.href = data.url;
} else {
$("#error_message").html(data.message);
}
}
controller code section below
//success case
render(contentType: 'text/json') {
[success: true, url: createLink(controller: 'whateverController', action: 'whateverAction')]
}
}
else {
render(contentType: 'text/json') {
["success": false, "message": 'Login or Password is incorrect.']
}
importing JSON converter in last set of code isn't needed either.
You are correct that you can't send a redirect using ajax. What you can do, however, is send something back in your ajax response that you can read and redirect if needed.
Instead of just updating the div with the response from your ajax call you will need to send back some JSON data and use the onSuccess attribute of the formRemote tag to pass the results to a function which can act accordingly.
I would suggest you start by reading over the documentation for the formRemote tag, then consider something like the following:
<g:formRemote name="subForm" url="[controller:'admin', action:'authenticate']" onSuccess="doResult(e)">
<br><br><label>User Name (email): </label><g:textField name="username" /><br><br>
<label>Password: </label><g:field name="password" type="password" /><br><br><br><br>
<div id="error_message" style="text-align: center"> </div>
<div style="text-align: center">(for TWC employees only)</div>
<g:submitButton id="submit_button" name="Submit"/>
</g:formRemote>
Notice in the above that onSuccess is now set on the formRemote tag and update is removed. The response from the form submission will now be passed to the javascript function doResult.
This is what the function might look like:
<script>
function doResult(response) {
var result = eval('(' + response.responseText + ')');
if (result.success == true) {
window.location.href = result.url;
} else {
$("#error_message").html(result.message);
}
}
</script>
The only thing left is to change how your controller responds to the form submission. First you will need to add the import for import grails.converters.JSON into your controller. Then change the way it responds. It might look like this:
import import grails.converters.JSON
...
// in the case of an error
render [success: false, message: "Login or Password incorrect!"] as JSON
return
...
// in the case of success
render [success: true, url: createLink(controller: 'whateverController', action: 'whateverAction')] as JSON
return
It may seem like a lot to take in all at once, but once you do it a few times it becomes quite simple. One thing that helps a lot is to read the Grails documentation. It's long, but it's very well written and will help a lot.
been frustrated with this for a couple days and was wondering if anyone could help. I'm new to Ajax and trying to post data from a login form in order to login to Django (Django Userena). However, when I try to post the data, alert() shows me the error in data as [object object]. I can't even see the network error code because the POST gets canceled before it can run.
Is there a way to just send the data and not the entire JSON array that I think its sending, or do I need to parse it out on the Django view backend. What is the best way to accomplish this code wise? Thank you very much!
Below is the relevant code:
Ajax Code:
$('#login').submit(function(){
$.ajax({
url: 'http://127.0.0.1:8000/accounts/signin/',
type: 'POST',
data: {
csrfmiddlewaretoken: '{{csrf_token}}',
identification: $("#id_identification").val(),
password: $("#id_password").val(),
},
success: function() {
alert('Test');
$('#datadisplay').append("<h2>It worked</h2>");
},
error: function(errorThrown){
console.log(errorThrown);
alert('Error');
alert(errorThrown);
}
});
});
Form on Index.html
<form name="login" id="login" action="">
<fieldset>
<label for="id_identification">Email or username</label>
<input class="required" id="id_identification" maxlength="75" name="identification" type="text" />
<label for="id_password">Password</label>
<input class="required" id="id_password" name="password" type="password" />
<input type="submit" name="submit" class="loginbutton" value="Login" />
</fieldset>
</form>
views.py from Django-Userena
#secure_required
def signin(request, auth_form=AuthenticationForm,
template_name='userena/signin_form.html',
redirect_field_name=REDIRECT_FIELD_NAME,
redirect_signin_function=signin_redirect, extra_context=None):
"""
Signin using email or username with password.
Signs a user in by combining email/username with password. If the
combination is correct and the user :func:`is_active` the
:func:`redirect_signin_function` is called with the arguments
``REDIRECT_FIELD_NAME`` and an instance of the :class:`User` who is is
trying the login. The returned value of the function will be the URL that
is redirected to.
A user can also select to be remembered for ``USERENA_REMEMBER_DAYS``.
:param auth_form:
Form to use for signing the user in. Defaults to the
:class:`AuthenticationForm` supplied by userena.
:param template_name:
String defining the name of the template to use. Defaults to
``userena/signin_form.html``.
:param redirect_field_name:
Form field name which contains the value for a redirect to the
succeeding page. Defaults to ``next`` and is set in
``REDIRECT_FIELD_NAME`` setting.
:param redirect_signin_function:
Function which handles the redirect. This functions gets the value of
``REDIRECT_FIELD_NAME`` and the :class:`User` who has logged in. It
must return a string which specifies the URI to redirect to.
:param extra_context:
A dictionary containing extra variables that should be passed to the
rendered template. The ``form`` key is always the ``auth_form``.
**Context**
``form``
Form used for authentication supplied by ``auth_form``.
"""
form = auth_form()
if request.method == 'POST':
form = auth_form(request.POST, request.FILES)
if form.is_valid():
#identification, password, remember_me = (form.cleaned_data['identification'],
#form.cleaned_data['password'],
#form.cleaned_data['remember_me'])
identification, password = (form.cleaned_data['identification'], form.cleaned_data['password'])
user = authenticate(identification=identification,
password=password)
if user.is_active:
login(request, user)
if remember_me:
request.session.set_expiry(userena_settings.USERENA_REMEMBER_ME_DAYS[1] * 86400)
else: request.session.set_expiry(0)
if userena_settings.USERENA_USE_MESSAGES:
messages.success(request, _('You have been signed in.'),
fail_silently=True)
# Whereto now?
redirect_to = redirect_signin_function(
request.REQUEST.get(redirect_field_name), user)
return HttpResponseRedirect(redirect_to)
else:
return redirect(reverse('userena_disabled',
kwargs={'username': user.username}))
if not extra_context: extra_context = dict()
extra_context.update({
'form': form,
'next': request.REQUEST.get(redirect_field_name),
})
return ExtraContextTemplateView.as_view(template_name=template_name,
extra_context=extra_context)(request)
AuthenticationForm
class AuthenticationForm(forms.Form):
"""
A custom form where the identification can be a e-mail address or username.
"""
identification = identification_field_factory(_(u"Email or username"),
_(u"Either supply us with your email or username."))
password = forms.CharField(label=_("Password"),
widget=forms.PasswordInput(attrs=attrs_dict, render_value=False))
remember_me = forms.BooleanField(widget=forms.CheckboxInput(),
required=False,
label=_(u'Remember me for %(days)s') % {'days': _(userena_settings.USERENA_REMEMBER_ME_DAYS[0])})
def __init__(self, *args, **kwargs):
""" A custom init because we need to change the label if no usernames is used """
super(AuthenticationForm, self).__init__(*args, **kwargs)
# Dirty hack, somehow the label doesn't get translated without declaring
# it again here.
self.fields['remember_me'].label = _(u'Remember me for %(days)s') % {'days': _(userena_settings.USERENA_REMEMBER_ME_DAYS[0])}
if userena_settings.USERENA_WITHOUT_USERNAMES:
self.fields['identification'] = identification_field_factory(_(u"Email"),
_(u"Please supply your email."))
def clean(self):
"""
Checks for the identification and password.
If the combination can't be found will raise an invalid sign in error.
"""
identification = self.cleaned_data.get('identification')
password = self.cleaned_data.get('password')
if identification and password:
user = authenticate(identification=identification, password=password)
if user is None:
raise forms.ValidationError(_(u"Please enter a correct username or email and password. Note that both fields are case-sensitive."))
return self.cleaned_data
These are the errors (not all and I think there are more) I see when I test your codes:
how can you login if you didn't use your AuthenticationForm() in your template. You form codes in the template is different.
you didn't put method="POST" in your form which result on GET response instead of POST.
you forgot to put {% csrf_token %} in your template form
In your views.py, user = authenticate(identification=identification, password=password) must be user = authenticate(username=identification, password=password)
In your forms.py, user = authenticate(identification=identification, password=password) must be user = authenticate(username=identification, password=password)
Your ajax codes has no effect that's why you can't get the error thrown. I think your missing something in your ajax.
To get the details of the error thrown:
error: function(ts){
//console.log(errorThrown);
//alert('Error');
alert(ts.responseText);
}
your ajax data must have '':
data: {
'csrfmiddlewaretoken': '{{csrf_token}}',
'identification': $("#id_identification").val(),
'password': $("#id_password").val(),
},
You don't have to elaborate your url like this one
url: 'http://127.0.0.1:8000/accounts/signin/',
It will result to
"http://127.0.0.1:8000/http://127.0.0.1:8000/accounts/signin/"
It must be
url: '/accounts/signin/',
and don't also forget to put
contentType: "application/json;charset=utf-8",
dataType: "json",
There are more errors and until now I can't successfully login.
I don`t speak english well? but i have problem in Django.
I have models:
class Model1(models.Model):
model2 = models.ManyToManyField(Model2)
#...
class Model2(models.Model):
model3 = models.ForeignKey(Model3)
#...
class Model3(models.Model):
custom = models.CharField()
have view
def simple(request, simple_id):
if request.method == 'POST':
if request.is_ajax():
if 'delete' in request.POST:
id3 = request.POST.get('delete', '')
Model1.objects.get(id = simple_id).model2.filter(model3__id = id3).delete()
That is, when submitting a form with name = "delete" Ajax have removed all the objects belonging to Model2 with the same value of the field "model3"
Here's a piece of template:
<form action="" method="post" id="simple">{% csrf_token %}
<input type="submit" name="delete" id="simple_delete" value="">
</form>
the value passed from js:
$('.deletebutton').click(function(){
id = $(this).attr('data-id');
$('#simple_delete').attr('value', id);
$('#simple').ajaxForm();
$('#simple_delete').click();
});
Well, respectively plugin jquery.form.js also connected
The problem is this - if submission without ajax all is normal, it works ... and if with Ajax is an error such as incorrect int value ... How to make it work via Ajax?
try this
$('.deletebutton').click(function(){
id = $(this).attr('data-id');
$.ajax(function(){
type:"POST",
url :"/your_url/",
data:{
'id'=id,
}
}).done(function(result){
alert('your json object result render by view :'+result)
})
i think it work,
and i didnt get wat you are doing in i.e $('#simple_delete').click();
can you please describe about that
in view
obj = Model1.objects.get(id = simple_id)
model2.objects.filter(model3__id = id3).delete()
i just split single line query into two lines and if not working
use .select_related()
I am a newb to django forms and I am trying to create a very specific user interface, so I can't use model forms (or can I?)
I created a custom form that looks like this:
but it won't commit to the db?
This is my html form:
<form method="POST" action='/create/' id="big_idea_form" class="tabscontent">{% csrf_token %}
<label class="tabpage" id="tabpage_1" ><span>next</span><p>Give it a name!</p><input type="text" id="name" placeholder="Type your title here" onblur='changeIt("name", "name_span")'/></label>
<label class="tabpage" id="tabpage_2" ><p>What is it about?</p><input type="text" id="subtitle" name="subtitle" placeholder="Type your subtitle here" onblur='changeIt("subtitle", "subtitle_span")'/></label>
<label class="tabpage" id="tabpage_3" ><p>Why is it important?</p><textarea id="description" name= "description" cols="42" rows="5" placeholder="this can be any description but it becomes more interesting if you can explain why it is important as part of your description" onblur='changeIt("description", "description_span")'></textarea></label>
<label class="tabpage" id="tabpage_4" ><p id="success_title">What is considered success?</p><textarea id="success" name="success" cols="42" rows="5" placeholder="describe what sucess means to your students... what does mastery look like?" onblur='changeIt("success", "success_span")'></textarea></label>
<input type="submit" value="Submit"/>
</form>
This is my form:
from django import forms
import urlparse
from models import Lesson
class CreateLesson(forms.Form):
name=forms.CharField()
subtitle=forms.CharField(required=False)
creator=forms.CharField() #automate
description=forms.CharField()
success=forms.CharField()
unit=forms.CharField(required=False)
public=forms.BooleanField()
def save(self, request):
data=self.cleaned_data
Lesson.creator = request.user
Lesson.name=data.get('name', '')
Lesson.subtitle=data.get('subtitle', '')
Lesson.topic=data.get('topic', '')
Lesson.description=data.get('description', '')
Lesson.unit=data.get('unit', '')
Lesson.public=data.get('public', True)
Lesson.save()
return Lesson
And here is my view:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from forms import CreateLesson
def Create_Lesson(request):
if request.method == 'POST': # If the form has been submitted...
form = CreateLesson(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
form.save()
return HttpResponseRedirect('/create/') # Redirect after POST
else:
form = CreateLesson() # An unbound form
return render(request, 'create_lesson/new_ideas.html', {
'form': form,
})
problem was that the form was not validating because there were fields in the model not represented on the form...
i simplified the form by using ModelForm and exclude as such
forms.py
class CreateLessonModel(forms.ModelForm):
class Meta:
model = Lesson
exclude =('unit', 'slug', 'topic', 'public', 'created_date', 'creator')
views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from forms import CreateLessonModel
from django.template.defaultfilters import slugify
def Create_Lesson(request):
if request.method == "POST": # If the form has been submitted...
form = CreateLessonModel(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
lesson = form.save(commit=False)
lesson.creator = request.user
lesson.slug = slugify(lesson.name)
lesson.save()
return HttpResponseRedirect('') # Redirect after POST
else:
form = CreateLessonModel() # An unbound form
return render(request, 'create_lesson/new_ideas.html', {
'form': form,
})