PimenTech libcommonDjango API

Installation

This package require python-docutils

svn checkout http://svn.pimentech.org/pimentech/libcommonDjango
cd libcommonDjango
make install

Trac access : http://trac.pimentech.org/pimentech/browser/libcommonDjango

Django admin modules

CSV and Stats modules

We have started to add some modules to admin interface. The CSV module allow to import export data files per table, in admin fields order. It supports multiple encodings.

/static/libcommonDjango/doc/csv_buttons.png

New buttons on admin lists.

/static/libcommonDjango/doc/csv_form.png

CSV Import/Export form

Add/Change stages

The admin add/change stage function have been overloaded by pim change/add stage functions : if creation_auth_user and modification_auth_user fields are present in table, these fields are updated with logged user.id.

Installation

  • in settings.py, put 'django_pimentech.common' in INSTALLED_APPS list, before 'django.contrib.admin'.
  • in urls.py, replace 'django.contrib.admin.urls' by 'django_pimentech.common.urls'

Custom Fields

FrenchDateField

This field allows you to display the date in the french format (dd/mm/yyyy). It also provides extra-options to purpose a calendar beside the field.

In order to use the calendar, you have to include the following javascripts in your header (adapt the urls according to your own settings):

index.html

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Django_calendar Demo</title>
          <script type="text/javascript" src="/admin/jsi18n/"></script>
          <script type="text/javascript" src="/admin_media/js/core.js"></script>
          <script type="text/javascript" src="/admin_media/js/admin/RelatedObjectLookups.js"></script>
          <script type="text/javascript" src="/admin_media/js/calendar.js"></script>
          <script type="text/javascript" src="/pimentech/js/django_calendar.js"></script>

          <!-- Here a style for the calendar-->
          <style type="text/css">
            .calendarlink { padding-left:12px; background:url(/static/img/icon_calendar.gif) 0 .2em no-repeat; }
          </style>

    </head>
</html>

The django_calendar.js scripts is provided by the Pimentech Scripts library

Here an example of a view using the FrenchDateField:

views.py

from django_pimentech.fields import *

class MyForm(Form):
  """A basic form."""
  ...
  my_french_date = FrenchDateField(required=True, initial=date.today(),
    widget=FrenchDateInput(attrs={'class':'type-date', 'calendar':True,\
                                                                      'calendar_class':'calendarlink'}))

def my_view(request):
  ...
      form = MyForm()
      return render_to_response('my_app/my_template.html',
                                                        {'form':form,},
                                                        context_instance=RequestContext(request))

The template file may looks like that:

my_template.html

<?xml version="1.0" encoding="utf-8"?>

<form id="my_form" name="my_form" action="{{ request.path }}" method="post">
   {{ form.my_french_date }} {{ form.errors.my_french_date }}
   <input type="submit" name="submit" value="Go!"/>
</form>

Et voilà :

/static/libcommonDjango/doc/django_calendar.png

Utils

Function : get_object_or_404(klass, args, kwargs)

Replaces django's get_object_or_404() function (too much SQL joins).

Example :

from django_pimentech.utils import get_object_or_404
K = get_object_or_404(Klass, uid=1)

In progress

Sorry for the lack of documentation, we are too busy for the moment..

Backoffice form modules with validating functions

http://svn.pimentech.org/pimentech/libcommonDjango/django_pimentech/validationforms.py

With this module, you can do modifications on your database with post-validation : if a row is modified, a copy is generated for post (un)validation. Works with 1-n and n-n relations.

DbHandler, a Django-ORM alternative

http://svn.pimentech.org/pimentech/libcommonDjango/django_pimentech/dbhandler.py

If like us, you create django applications on existing models, using the Django ORM is often inadequate : database model is not application oriented. With this module, you can build application-oriented classes with sql queries.

Log

Loguer des messages dans le code

Fonctions permettant d'écrire des messages sur stdout en mode 'runserver' ou dans le fichier de log 'error' d'Apache. Les fonctions sont :

  • message() - logue avec le flag APLOG_NOTICE
  • warning() - logue avec le flag APLOG_WARNING
  • error() - logue avec le flag APLOG_ERR

Exemple :

import django_pimentech.log as log
l = (1, 2, 3)
log.message(l)

Loguer les erreurs Django

Le middleware ErrorLogMiddleware permet de stocker les erreurs Django dans /var/log/django.

Exemple de fichier settings.py :

MIDDLEWARE_CLASSES = (
        'django.middleware.common.CommonMiddleware',
        'django_pimentech.errorlog_middleware.ErrorLogMiddleware',
)

Ensuite un simple lien dans /var/www vers /var/log/django permettra de récupérer les erreurs au format HTML.

Network

Classe : JSONRPCService

Cette classe permet de créer un service JSON-RPC en Django (http://json-rpc.org/). Le code est largement inspiré de celui trouvé sur le wiki de Pyjamas (http://trac.pyworks.org/pyjamas/wiki/DjangoWithPyJamas) à la différence que le paramètre request est transmis aux vues distantes, comme pour les vues classiques.

L'exemple suivant montre comment créer une vue invoquable par JSONRPC. Celle-ci prend une chaîne de caractère en paramètre et renvoie la même chaîne en majuscules.

Fichier stringservices/views.py :

from django_pimentech.network import *

service = JSONRPCService()

def to_upper(request, str):
        return str.upper()
service.add_method("to_upper", to_upper)

Note

A partir de python 2.4, il est possible d'utiliser le décorateur jsonremote pour un code plus élégant.

Fichier stringservices/views.py (python >= 2.4) :

from django_pimentech.network import *

service = JSONRPCService()

@jsonremote(service, 'to_upper')
def to_upper(request, str):
        return str.upper()

Dans le fichier urls.py, il suffit d'ajouter une règle pour transmettre les requêtes JSON-RPC à notre objet JSONRPCService :

(r'^/chatservice-jsonrpc/$', 'stringservice.views.service'),

logprofile

Ce module permet de faire du profiling. Il nécessite le module non libre python-profiler.

  • create_profile(name) : renvoie un objet de profiling
  • log_stats(name, *sort, *result) : tableau des stats
  • log_callers(name, *sort, *result) : stats par fonction appellée

Exemple :

from django_pimentech.logprofile import *

prof = create_profile("/tmp/file.prof")
# on peut ainsi recuperer le fichier de profile pour analyse

prof.start()

... some python code ...

prof.stop()
prof.close()

# standard (time, call)
profile_stats = log_stats("/tmp/file.prof") + "\n"

# filtre sur une fonction et 25% des resultats :
profile_stats += log_stats("/tmp/file.prof", result=['funcname', 0.25]) + "\n"

# filtre avec tri par nom de fonction puis par nombre d'appels:
profile_stats += log_stats("/tmp/file.prof", sort=['name', 'calls'] + "\n"

print profile_stats

Voir http://www.python.org/doc/2.3/lib/profile-stats.html pour plus d'infos sur les tris et résultats possibles.

Voir également http://code.djangoproject.com/wiki/ProfilingDjango pour la page officielle.

Templatetags

Un ensemble de templatetags réutilisables sont fournis par l'application gdjango_pimentech.common (à ajouter dans la variable INSTALLED_APPS de settings.py).

Navigation page à page

Pour utiliser le module de navigation par pages, il suffit de mettre dans le template :

{% load pimentech_extras %}

{% pages_navigation nb_results page nb_per_page %}

Les trois paramètres à passer à pages_navigation sont : le nombre total de résultats, le numéro de la page courante, et le nombre de résultats par page (15 si non spécifié).

Les variables suivantes sont fournies au template chargé de représenter le module de navigation :

  • page : le numéro de la page courante
  • prev_pages : la liste des 4 pages précédant la page courante (ou moins si page < 4.
  • prev_page : la page précédente, ou None si pas de précédent.
  • next_pages : la liste des 4 pages suivant la page courante (ou moins)
  • next_page : la page suivante, ou None si pas de suivant.

Un template par défaut est fourni dans libcommonDjango. Il est possible de le modifier en redéfinissant localement le template common/pages_navigation.html.

Voici le template par défaut :

{% load i18n %}

{% if prev_pages %}
<a href="?{{ append_get }}page={{ prev_page }}" title="{% trans 'Previous Page' %}">&lt;&lt;</a>
{% for p in prev_pages %}
<a href="?{{ append_get }}page={{ p }}" title="{% trans 'Page' %} {{ p }}">{{ p }}</a> -
{% endfor %}
{% else %}
&lt;&lt;
{% endif %}
{% trans 'Page' %} {{ page }}
{% if next_pages %}
{% for p in next_pages %}
- <a href="?{{ append_get }}page={{ p }}" title="{% trans 'Page' %} {{ p }}">{{ p }}</a>
{% endfor %}
<a href="?{{ append_get }}page={{ next_page }}" title="{% trans 'Next Page' %}">&gt;&gt;</a>
{% else %}
&gt;&gt;
{% endif %}

Cache

Fonction : cache_force_view_expiration(path, key_prefix=None)

Cette fonction permet de forcer l'expiration d'une vue dans le cache Django. Elle prend en paramètre une URL absolue, menant à la vue que l'on souhaite supprimer du cache. Elle prend également un paramètre optionnel key_prefix, qui a comme valeur par défaut settings.CACHE_MIDDLEWARE_KEY_PREFIX (il permet de générer la signature de la vue dans le cache). Si une vue peut être invoquée depuis deux chemins différents avec les mêmes paramètres, seule la page dont le chemin a été passé à cache_force_view_expiration sera recalculée. cache_force_view_expiration peut par exemple être invoquée suite à la modification d'un objet afin qu'une page soit recalculée au prochain hit.

Fichier views.py :

from django.views.decorators.cache import cache_page

def ma_vue_cachee(request, param):
        (...)
        return (...)
ma_vue_cachee = cache_page(ma_vue_cachee, 60 * 15) # expiration de la version cache dans 15 minutes

Fichier urls.py :

from django.conf.urls.defaults import *

urlpatterns = patterns('mon_appli.views',
                (r'^ma-vue-cachee-(?P<numero>\d+)/$', 'ma_vue_cachee'),
(...)

Demande d'expiration explicite d'une vue :

from django_pimentech.cache import cache_force_view_expiration

cache_force_view_expiration('/mon-appli/ma-vue-cachee-18/')

Commentaires

akh Mai 13, 2007 at 11:10 après-midi

Sympa !

mais c est opensource ?si oui ce n'est pas sur votre ftp

nick Février 19, 2008 at 12:09 matin

Very nice stuff. I am very interested in the CSV import/export functionality.

What version of Django is this code written against? Against dev (.97) I am getting...

<ExtendsNode: extends "admin/import_form.html"> must be the first tag in the template.

...in /django/template/__init__.py. Should one of your templates be taking over?

fredz Février 19, 2008 at 10:06 matin

Sorry, we are in 0.96 version, and I have no time to look at changes in dev version...

nick Février 19, 2008 at 4:11 après-midi

Well, I'm probably going to port it, then.

Would you like the results of the changes?

fredz Février 19, 2008 at 4:15 après-midi

Sure, that would be great

Ana Novembre 12, 2008 at 10:38 matin

Hi, I'm very interesting in CSV and Stats modules but the link http://trac.pimentech.org/pimentech/brow... is falling down . Existe any other place to download it? or can arrange this links?
I need it very much.

Thanks.

fredz Novembre 12, 2008 at 10:46 matin

Hi, for uknown reason, trac seems to lock svn repository. I've removed the trac link. See on top for getting the module.

Fred.

Ana Novembre 17, 2008 at 12:50 après-midi

Thanks very much, now it works!. Just a question, finally exists a version for django 1.0? it wold be great, i'm new in django framework and i'm not capable of port it myself.

fredz Novembre 17, 2008 at 1:09 après-midi

Sorry but we only use django 1.0 on new projects, which doesn't need csv and stat modules for the moment....

Ana Novembre 17, 2008 at 6:05 après-midi

Thank you for responding so quickly, it is a pity you do not have it for 1.0. make the great work

Brian Septembre 3, 2009 at 11:30 matin

Hi, just wanted to say that it seems to be working with Django 1.1. I am using the svn versions of Django and Pyjamas. To get the DjangoTask example to work in pyjamas all I had to do was copying

libcommonDjango.tgz\libcommonDjango\build\lib\django\pimentech

to

\django\django\pimentech

(this was on a Windows box)

Comments

blog comments powered by Disqus