1. arikon.livejournal.com

    04.10.2008 15:30

    Используем django.contrib.auth
    После того, как пользователь вводит неверные логин и пароль, показываем пользователю сообщение и заполненную форму (виджеты формы выводим как {{ form.password }}, например).
    Задача - не выводить пользователю пароль, но выводить логин.
    Как быть? Бьюсь уже целый час.
  2. Иван Сагалаев

    04.10.2008 16:02

    Немножко не-DRY, но самое простое наверное решение:

    {% if not form.errors %}
    {{ form.password }}
    {% else %}
    <input type="password" name="{{ form.password.name }}">
    {% endif %}
    

    Чтобы присоветовать что-то более "robust", надо понять, кто и как создает сам объект формы.

  3. Иван Сагалаев

    04.10.2008 16:04

    ... в том смысле, что если форма создается в своем коде, а не в чужом, можно например пароль из ее data удалить, можно свой виджет над PasswordInput'ом написать.

  4. arikon.livejournal.com

    04.10.2008 16:09

    Ваня, я ожидал чего-нибудь вроде
    form['password'].value = ''
    =)

    Первый вариант не годится, потому что совсем не DRY.

    Форма создается в своем коде, да.
    Но её при создании необходимо накормить логином и паролем, чтобы логин и пароль провалидировались через
    auth-backend. А вот перед отрисовкой формы пароль хорошо бы выкинуть или обнулить.
  5. Иван Сагалаев

    04.10.2008 16:12

    Тогда так:

    if not form.is_valid():
        form.data = form.data.copy() # иначе там request.POST, который read-only
        del form.data['password']
    
  6. Иван Сагалаев

    04.10.2008 16:13

    Да, но кстати... По-моему ты зря это делаешь :-). Если юзер только что сам ввел этот пароль, почему бы ему его и не показать снова. Особенно учитывая, что это результат POST'а, и никто его не кеширует даже.

  7. arikon.livejournal.com

    04.10.2008 16:14

    Для ясности - код:
    from django.contrib.auth.forms import AuthenticationForm as AuthenticationFormOrig
    from django.utils.translation import ugettext as _

    class AuthenticationForm(AuthenticationFormOrig):
    username = forms.CharField(label=_("Username"), max_length=30, widget=forms.TextInput(attrs={'tabindex': 1}))
    password = forms.CharField(label=_("Password"), widget=forms.PasswordInput(attrs={'tabindex': 2}))
    # ... тут еще пара полей и методов

    def login(request, template_name='login.html', redirect_field_name=settings.REDIRECT_FIELD_NAME):
    "Displays the login form and handles the login action."
    redirect_to = request.REQUEST.get(redirect_field_name, settings.LOGIN_REDIRECT_URL)

    if request.user.is_authenticated():
    return HttpResponseRedirect(redirect_to)

    if request.method == "POST":
    form = AuthenticationForm(data=request.POST)
    if form.is_valid():
    from cool_auth_module import login
    login(request, form.get_user())
    return HttpResponseRedirect(redirect_to)
    else:
    form = AuthenticationForm(request)

    # TODO: где-то тут нужно обнулить значение form['password']
  8. arikon.livejournal.com

    04.10.2008 16:16

    Яндекс.Паспорт же неправильный пароль юзеру не показывает ;)
  9. arikon.livejournal.com

    04.10.2008 16:21

    Спасибо! Вариант с data.copy() подошел.
  10. Иван Сагалаев

    04.10.2008 16:21

    Хм... Яндекс, в общем-то, не истина в последней инстанции в вопросах веб-разработки. Тот же Яндекс.Паспорт например до сих пор вешает ?ncrnd=... на редиректы через себя, хотя надобность, на мой взгляд, отпала уже много лет назад.

  11. Иван Сагалаев

    04.10.2008 16:33

    Ба! Только что нашел прямой способ это делать:

    ..., widget=forms.PasswordInput(render_value=False, attrs={...})
    

    P.S. Use the Source, Luke!

  12. arikon.livejournal.com

    04.10.2008 16:43

    Опаньки =)
    В мануале про это ни слова не было.
    Спасибо!

bbcode