понедельник, 31 октября 2011 г.

django: пример Ajax-аутентификации


В данной статье описывается пример реализации ajax-аутентификации в django.
На стороне клиента используется js-фреймворк Dojo. Ничто не мешает взять любой другой, например jquery.
Итак приступим:
1. определяем специальный view для обработки ajax-запросов (используем только POST)
#views.py
from django.contrib.auth.forms import AuthenticationForm
@csrf_protect #предварительно в settings.py надо подключить соответствующее moddleware
@never_cache
def ajax_login(request, template_name='registration/login.html',
          redirect_field_name=REDIRECT_FIELD_NAME,
          authentication_form=AuthenticationForm,
          current_app=None, extra_context=None):
    logger = logging.getLogger(__name__)
    manipulator = AuthenticationForm(request)
    redirect_to = request.REQUEST.get(redirect_field_name, '')
    if request.method == "POST":
        form = authentication_form(data=request.POST)
        if form.is_valid():
            netloc = urlparse.urlparse(redirect_to)[1]
            auth_login(request, form.get_user())
            if request.session.test_cookie_worked():
                request.session.delete_test_cookie()
            logger.error('SUCCESS')
            return HttpResponse(simplejson.dumps("OK"))
        else:
            logger.error('FAILED')
            return HttpResponse(simplejson.dumps("FAIL"))
    else:
        return HttpResponseRedirect('/');
        form = authentication_form(request)
    request.session.set_test_cookie()
    current_site = get_current_site(request)
    context = {
        'form': form,
        redirect_field_name: redirect_to,
        'site': current_site,
        'site_name': current_site.name,
    }
    context.update(extra_context or {})
    return render_to_response(template_name, context,
                              context_instance=RequestContext(request, current_app=current_app))

2. вставим в соответствие конкретному url определенную выше view

from my_auth_app.views import ajax_login

urlpatterns += patterns('',
    url(r'^login/ajax', ajax_login),
)

3. Описываем шаблон формы и клиентскую js-часть:

<script>
    var sendLoginButton;
    function sendLogin(){
      dojo.xhrPost({
        url: '/login/ajax/',
        load:sendLoginCallback,
        form: dojo.byId('loginForm'),
        handleAs: "json",
        error: function(response,ioArgs) {
         dojo.byId("messagestatus").innerHTML = "Попробуйте еще раз!";
         dojo.byId("loginForm").style.display = "yes";
      });
      dojo.byId("loginForm").style.display = "none";
      dojo.byId("messagestatus").innerHTML = "Проверка...";
    }

    function sendLoginCallback(type, data, evt) {
      console.error(type);
      console.error(data);
      console.error(evt);
      if (type == 'FAIL'){
         dojo.byId("messagestatus").innerHTML = "Попробуйте еще раз!";
         dojo.byId("loginForm").style.display = "";
      }
      else {
        if (data == "false") {
          dojo.byId("loginForm").style.display = "";
          dojo.byId("messagestatus").innerHTML = "Your password or username is invalid";
          dojo.disconnect(sendLoginButton, 'onclick', 'sendLogin');
          var anim = dojo.lfx.html.highlight("messagestatus", [255, 0, 0], 200).play(100);
          dojo.connect(anim, "onEnd", function() {  dojo.connect(sendLoginButton, 'onclick', 'sendLogin'); });

        }
        else {
           window.location="/";
        }
      }
    }
    function init(){
      console.log(document.cookie);
      sendLoginButton = dojo.byId('loginButton');
      var loginForm = dojo.byId('loginForm');
      if(loginForm){
          loginForm.onsubmit = function() { return false; }
          dojo.connect(sendLoginButton, 'onclick', 'sendLogin');
      }
   }
   dojo.addOnLoad(init);
</script>
<div id="messagestatus"></div>
{% if user.is_authenticated %}
<p id="welcome">Хелло, {{user.username}}</p>
{% else %}
  <form  method="post" id="loginForm" class="blocks">
  {%if form.errors %}
    Неудачный вход.
  {% endif %}
     <label for="id_user">Ник:</label> {{ form.username }}
   Ошибка:{{form.username.errors}}
Пояснение:{{ form.username.help_text }}
  <label for="id_password">Пароль:</label> {{ form.password }}
 Ошибка:{{form.password.errors }}
Пояснение:{{ form.password.help_text }}
<input id="loginButton" class="large button" type="submit" value="ВОЙТИ" />
  </form>
{% endif %}

среда, 12 октября 2011 г.

perl: несколько проблем установкой GD и способы их решения

Сегодня потребовалась установка CPAN-модуля GD.pm на один из серверов.
При установке возникла ошибка:

perl -MCPAN -e 'install "GD"'

we get the following fatal error message:
**UNRECOVERABLE ERROR**
Could not find gdlib-config in the search path. Please install libgd
2.0.28 or higher.
If you want to try to compile anyway, please rerun this script with
the option --ignore_missing_gd. 
...

Ок, пытаюсь ставить libgd из репозитория (Debian 5 Lenny):

$ apt-get install libgd2-xpm
$ apt-get install libgd2-xpm-dev

Пробую ставить опять perl-модуль - та же ошибка.

Раскопки и гуглеж позволили выяснить, что дело в том, что в штатный пакет не входит скрипт gdlib-config.

Решить проблему можно , поставив libgd самостоятельно, взяв исходники, например, отсюда

$ wget http://www.boutell.com/gd/http/gd-2.0.28.tar.gz
$ tar xvf gd-2.0.28.tar.gz
$ cd gd-2.0.28
$ ./configure --prefix=/usr
$ make
$ sudo make install

После этого повторяем попытку поставить GD.pm.

Может возникнуть еще одна проблема:
Manifying blib/man3/GD::Polygon.3pm
  LDS/GD-2.46.tar.gz
  /usr/bin/make -- OK
Warning (usually harmless): 'YAML' not installed, will not store persistent state
Running make test
PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/GD..........Testing using png support.
t/GD..........FAILED test 10                                                 
        Failed 1/12 tests, 91.67% okay
t/Polyline....ok                                                             
Failed Test Stat Wstat Total Fail  List of Failed
-------------------------------------------------------------------------------
t/GD.t                    12    1  10
Failed 1/2 test scripts. 1/13 subtests failed.
Files=2, Tests=13,  1 wallclock secs ( 0.12 cusr +  0.02 csys =  0.14 CPU)
Failed 1/2 test programs. 1/13 subtests failed.
make: *** [test_dynamic] Ошибка 255
  LDS/GD-2.46.tar.gz
  /usr/bin/make test -- NOT OK
//hint// to see the cpan-testers results for installing this module, try:
  reports LDS/GD-2.46.tar.gz
Warning (usually harmless): 'YAML' not installed, will not store persistent state
Running make install
  make test had returned bad status, won't install without force


Подозрение на отсутствие библиотеки libpng. Ставим ее:
# apt-get install libpng3 libpng3-dev

Опять пробуем ставить perl-модуль - опять то же самое.

Удаляем libgd, конфигурим , собираем и ставим ее заново.Делаем так, потому что изначально у нас не было libpng и , соответственно, libgd была собрана без ее поддержки. Надо пересобрать:

# в директории с исходниками GD
$ make clean 
$ ./configure --prefix=/usr
$ make 
$ sudo make install

После этого GD.pm должен установиться успешно.