Я такое аяксом делаю, только Class-Based View'хи использую, ну принцип похож конечно.
Смысл вообще в том что данные с формы отсылаются Ajax Postом.
Если логин ОК- пользователь логинится и страничка перегружается(можно и редиректить куда надо), если нет- в placeholder полей прилетают ошибки, довольно удобно получается в инпуты ошибки писать в обратку.
P.S. в 1.5 надо не забывать get_user_model() использовать для доступа к модели пользователя
Форма такая же в целом, ну я еще проверку добавляю.
class LoginForm(forms.Form):
username = forms.CharField(label=_('Username'), max_length=30)
password = forms.CharField(label=_('Password'), max_length=30)
class Meta:
widgets = dict(password=forms.PasswordInput)
def clean_username(self):
username = self.cleaned_data["username"]
if not username:
raise forms.ValidationError(_("THIS FIELD IS REQUIRED"))
try:
user = get_user_model().objects.get(username=username)
if not user.is_active:
raise UserIsDisabled
return username
except get_user_model().DoesNotExist:
raise forms.ValidationError(_("THE USER IS NOT EXIST"))
except UserIsDisabled:
raise forms.ValidationError(_("THE USER IS DISABLED"))
def clean_password(self):
username = self.cleaned_data["username"]
password = self.cleaned_data["password"]
user = authenticate(username=username, password=password)
if not user:
raise forms.ValidationError(_("THIS PASSWORD IS INCORRECT"))
return password
class LoginView(FormView):
form_class = LoginForm
def form_valid(self, form):
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
login(self.request, user)
payload = {'success': True}
return HttpResponse(json.dumps(payload, cls=LazyEncoder), content_type='application/json')
def form_invalid(self, form, *args, **kwargs):
# Ошибки формы кидаем в словарь, чтобы отправить клиенту, функция ниже
payload = {'success': False, 'errors': as_json(form.errors)}
return HttpResponse(json.dumps(payload, cls=LazyEncoder), content_type='application/json')
def as_json(errors):
return dict((k, map(unicode, v)) for k, v in errors.items())
На клиенте на отправку формы
// Просто функция которая пишет в Placeholder ошибки поля , а общие ошибки формы в добавленный перед формой DIV
function AjaxFormError(errors, $form) {
for (var k in errors) {
// Не забываем стереть введенные значения в форме, перед тем как записать ошибки
$('[name="'+k+'"]').val('').prop('placeholder', errors[k]);
if (k == '__all__') // Если ошибки не поля, а всей формы- допишем слой выше
{ $form.prepend('<div class="error">' + errors[k] + '</div>'); }
}
}
// Ииии..все вместе :)
$(document).ready(function(){
$('#login_link').click( function() {
$.post("{% url 'login' %}", $("#login_form").serialize(),function(data) {
$("#login_form").find('.error').html('');
if (data.success == true) { window.location.reload(); } else { AjaxFormError(data['errors'], $('#login_form')); }
});
return false;
});
})