Sam & Max » view http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Views VS generators 6 http://sametmax.com/views-vs-generators/ http://sametmax.com/views-vs-generators/#comments Wed, 25 Mar 2015 18:57:20 +0000 http://sametmax.com/?p=15993 Avec Python 2.7, un outil appelé les “views” (les “vues”) est apparu. Une vue est juste un enrobage qui permet de voir un objet d’une certaine façon, et de le manipuler d’une certaine façon (avec une autre API), sans changer cet objet.

Les vues ont surtout été notables pour leur apparition dans les dictionnaires avec Python 2.7:

    >>> scores = {"sam": 1, "max": 0}
    >>> scores.items() # retourne une lsite
    [('max', 0), ('sam', 1)]
    >>> scores.iteritems() # retourne un générateur
    <dictionary-itemiterator object at 0x7f8782a26628>
    >>> list(scores.iteritems()) # sans views
    [('max', 0), ('sam', 1)]
    >>> scores.viewsitems() # avec views
    Traceback (most recent call last):
      File "<ipython-input-12-dc0b08011047>", line 1, in <module>
        scores.viewsitems() # avec views
    AttributeError: 'dict' object has no attribute 'viewsitems'
 
    >>> scores.viewitems() # retourne une vue
    dict_items([('max', 0), ('sam', 1)])

Néanmoins personne ne les a vraiment utilisé, et c’est un tort. Elles sont en effet très performantes, et pour cette raison sont retournées par défaut avec items() en Python 3.

En effet, les vues ne sont qu’un enrobage : elles ne contiennent rien, et donc ne prennent pas beaucoup mémoire, tout comme les générateurs.

Mais contrairement aux générateurs, les vues ne se vident pas et peuvent exposer une API plus complète que les générateurs, comme par exemple déclarer une taille :

>>> items = scores.iteritems()
>>> list(items)
[('max', 0), ('sam', 1)]
>>> list(items) # woops
[]
>>> items = scores.viewitems()
>>> list(items)
[('max', 0), ('sam', 1)]
>>> list(items)
[('max', 0), ('sam', 1)]
>>> len(scores.iteritems()) # nope
Traceback (most recent call last):
  File "<ipython-input-21-9c7f250da51d>", line 1, in <module>
    len(scores.iteritems())
TypeError: object of type 'dictionary-itemiterator' has no len()
 
>>> len(scores.viewitems())
2

Alors certes, on ne peut pas mettre des vues partout, et les générateurs restent utiles. Mais quand il est possible de les utiliser, et à moins d’avoir besoin d’une liste afin de modifier les valeurs in place, il n’y pas de raison de ne pas le faire : c’est le meilleur des deux mondes.

]]>
http://sametmax.com/views-vs-generators/feed/ 6
Django, une app à la fois – faire une app de base 3 http://sametmax.com/django-une-app-a-la-fois-faire-une-app-de-base/ http://sametmax.com/django-une-app-a-la-fois-faire-une-app-de-base/#comments Sat, 18 Jan 2014 15:22:24 +0000 http://sametmax.com/?p=8789 Ca faisait longtemps que je n’avais pas fait avancer le projet django, an app at a time.

Voici donc un nouveau morceau qui montre comment écrire une petite app de base avec un template et une vue réutilisables qui serviront donc dans les prochaines apps du projet.

Comme d’hab, vous pouvez récupérer le code sur la teub de Guy et il y a une version française et anglaise.

]]>
http://sametmax.com/django-une-app-a-la-fois-faire-une-app-de-base/feed/ 3
La question du jour: qu’est-ce que l’objet context en Django 4 http://sametmax.com/la-question-du-jour-quest-ce-que-lobjet-context-en-django/ http://sametmax.com/la-question-du-jour-quest-ce-que-lobjet-context-en-django/#comments Sun, 12 Aug 2012 14:38:36 +0000 http://sametmax.com/?p=1643 J'apprends Django. Pouvez-vous me dire ce qu'est l'object context dans une méthode liée à une vue. Je vois vaguement ce qu'est l'objet request mais pas l'objet context? pouvez-vous m'en dire plus?]]> Petit mail aujourd’hui:

J’apprends Django. Pouvez-vous me dire ce qu’est l’object context dans une méthode liée à une vue. Je vois vaguement ce qu’est l’objet request mais pas l’objet context? pouvez-vous m’en dire plus?

L’objet context est ce qui permet de faire passer des valeurs depuis la vue au template.

Pour des raisons de performance, de sécurité et de facilité de débuggage, on ne veut pas passer toutes les variables d’une vue dans le template. On va donc créer un objet context, que l’on va remplir des trucs qu’on souhaite être accessibles depuis le template.

L’objet context ressemble à un dictionnaire: il a des clés et des valeurs. Il est d’ailleurs créé à partir d’un vrai dictionnaire, et la plupart du temps dans une vue on voit un truc comme ça:

tous_les_articles = Article.objects.all()
context = {'articles': tous_les_articles}
return render('index.html', context)

Typiquement cela veut dire “Renvoyer une réponse en utilisant le template index.html qui aura accès à la variable articles contenant des objets Article().).

Du coup, dans le template index.html, on pourra faire ça:

{{ articles }}

Mais pas ça:

{{ tous_les_articles }}

Car articles est dans le context, mais pas tous_les_articles. Même si dans notre cas on s’en branle puisqu’ils ont la même valeur.

Il y a un piège cependant dans cet exemple :-)

Context ici n’est PAS un objet context, mais par facilité on l’appelle ainsi. Ici context est un dictionnaire des valeurs que l’on veut mettre dans le vrai objet context. On passe ce dictionnaire à la fonction render() qui va se charger de la corvée de charger le template, créer le vrai objet context, lui passer les valeurs dans le dictionnaires, et faire le rendu du template avec ces valeurs puis retourner la réponse HTTP avec le résultat.

Je note que dans le question, notre interlocuteur nous parle de méthode. Si il utilise les vues génériques sous forme de classe (ce que je recommande d’éviter à tout prix), dans ce cas on retrouve le context généralement ainsi:

context = super(MaView, self).get_context_data(**kwargs)

Dans ce cas, context est le vrai objet context, déjà tout fait rien que pour vous par la vue. Mais comme il se comporte comme un dictionnaire, on peut très bien continuer à l’utiliser comme avant:

context['articles'] = Article.objects.all()
return context

Et du coup faire:

{{ articles }}

Dans le template spécifié dans l’attribut template_name de la classe.

Dans ce cas, la vue va se charger automatiquement de récupérer le context ainsi retourné, et de faire le rendu du template avec celui-ci. Ici ça à l’air un peu plus magique, et un débutant aura du mal à comprendre d’où vient le context et où va le context. C’est entre autre pour ça que je recommande de ne pas utiliser les vues sous forme de classe. Utilisez les fonctions, c’est beaucoup plus simple.

Une dernière chose: pourquoi utiliser un objet context, et pas juste un dictionnaire ? Après tout il s’agit juste d’avoir une liste des variables accessible dans le template non ?

En fait, le context peut faire bien plus. Notamment, il est possible de le remplir automatiquement pour toutes les vues au travers des context managers.

Par ailleurs, pour les questions sur Django, je vous recommande à tous de rejoindre le forum de Django-fr qui est justement là pour ça. On ouvrira un compte Sam&Max si personne ne répond :-)

]]>
http://sametmax.com/la-question-du-jour-quest-ce-que-lobjet-context-en-django/feed/ 4