Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Django
  • » Красивая обработка ошибки в форме авторизации [RSS Feed]

#1 Фев. 25, 2013 15:59:47

dnstuff
Зарегистрирован: 2012-11-05
Сообщения: 113
Репутация: +  1  -
Профиль   Отправить e-mail  

Красивая обработка ошибки в форме авторизации

Здравствуйте!
Django 1.5, использую такую форму для авторизации (используется переопределенная модель MyUser):
model:

class LoginForm(forms.Form):
    username = forms.CharField(max_length=100)
    password = forms.CharField(widget=forms.PasswordInput(render_value=False),max_length=100)
view:

def login_view(request):
	if request.method == 'POST':
		username = request.POST['email']
		password = request.POST['password']
		user = authenticate(username=username, password=password)
		if user is not None and user.is_active:
			login(request, user)
			return HttpResponseRedirect("/n1.html")# Redirect to a success page.
		return HttpResponseRedirect("/invalid/")# Return a 'disabled account' error message
	form=LoginForm()
	return render(request, 'enter.html', {'login_form': LoginForm})

urls:
(r'^login/$', login_view),
Как сделать, чтобы при неправильном вводе на этой же странице выдавалось сообщение об ошибке (которое можно было бы раскрасить при помощи того же jGrow, например), а не происходил редиррект на страницу с ошибкой.
P.S. Джанго изучаю недавно, пока никак не пойму, как реализуются такие действия на одной странице. В примерах как правило искусственные ситуации, когда сообщение об ошибке или, например, результаты опроса реализуются на отдельном url, хотя в жизни как правило так не делают.

Офлайн

#2 Фев. 25, 2013 19:30:09

barabansheg
От:
Зарегистрирован: 2011-10-16
Сообщения: 114
Репутация: +  2  -
Профиль   Отправить e-mail  

Красивая обработка ошибки в форме авторизации

Почитайте тут



Fidonet. Nod 2:5034/10. Идет набор. Подробности в личку.
Мой блог

Офлайн

#3 Фев. 26, 2013 00:38:40

nnmware
Зарегистрирован: 2012-07-21
Сообщения: 133
Репутация: +  13  -
Профиль   Отправить e-mail  

Красивая обработка ошибки в форме авторизации

Я такое аяксом делаю, только 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;
        });
})

Отредактировано nnmware (Фев. 26, 2013 00:47:04)

Офлайн

#4 Фев. 26, 2013 14:02:43

dnstuff
Зарегистрирован: 2012-11-05
Сообщения: 113
Репутация: +  1  -
Профиль   Отправить e-mail  

Красивая обработка ошибки в форме авторизации

nnmware
Спасибо. Но пока решил сделать попроще, чтоб самому было понятно:
view:
def login_view(request):
	if request.method == 'POST':
		username = request.POST['email']
		password = request.POST['password']
		user = authenticate(username=username, password=password)
		if user is not None and user.is_active:
			login(request, user)
			return HttpResponseRedirect("/n1.html")
		return render_to_response('enter.html', {'error': True})
	form=LoginForm()
	return render(request, 'enter.html', {'login_form': LoginForm})
enter.html
 {% if error %}
'Неверное имя или пароль'
 {% endif %}
    <form class="form-signin" action="" method="post">
    	{% csrf_token %}
    	<h2 class="form-signin-heading">Пожалуйста, авторизуйтесь</h2> 
        <input class="input-block-level" type="text" name="email" value="" id="email" placeholder="Email адрес">
        
        <input class="input-block-level" type="password" name="password" value="" id="username" placeholder="Пароль">
        <button class="btn btn-large btn-primary" type="submit">Вход</button>
        <input type="hidden" name="next" value="{{next|escape}}" >
        
    </form>
Но в Django, как я заметил, халява прокатывает редко.
В этот раз неведомый геморой такого вида: если ввести логин\пароль правильно, то всё отлично. Если ввести неправильно, то появиться сообщение об ошибке, как и задумывалось. Но! Если попробовать повторно ввести логин\пароль, получаем Forbidden (403) CSRF verification failed. Request aborted.
Сравниваю код первичной и повторной страницы. Действительно, в оригинале присутствует <input type='hidden' name='csrfmiddlewaretoken' value='mQBDiAVLwMxEcmafe3fI5XkLCcXieQ8S' />, а вот на повторной странице эта строчка чудесным образом исчезает! Что опять не так? Спасибо!

P.S.
Заменил return render_to_response('enter.html', {'error': True}) на return render(request, ‘enter.html’, {'error': True}) - заработало. Но я так и не понял, почему надо именно так делать.

Отредактировано dnstuff (Фев. 26, 2013 14:22:34)

Офлайн

#5 Фев. 26, 2013 15:50:45

nnmware
Зарегистрирован: 2012-07-21
Сообщения: 133
Репутация: +  13  -
Профиль   Отправить e-mail  

Красивая обработка ошибки в форме авторизации

Заработало бы и вот так - render_to_response('enter.html', {'error': True, context_instance=RequestContext(request) })
По умолчанию в render_to_response используются только данные из предоставленного словаря, в Вашем случае- только error. В шаблоне не виден request, а {% csrf_token %} из него дергает значение ключа, чтобы рендерить скрытое поле.
Соответственно чтобы использовать процессоры контекста- надо передать экземляр RequestContext.
http://djbook.ru/rel1.4/topics/http/shortcuts.html#id2

P.S. Судя по коду, если бы у Вас было debug=True, то джанга бы сама это сказала.

Офлайн

  • Начало
  • » Django
  • » Красивая обработка ошибки в форме авторизации[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version