Merge branch 'master' of https://grimbox.be/git/fred/gwift-book into master
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is failing Details

This commit is contained in:
Fred Pauchet 2020-09-16 21:53:17 +02:00
commit 04b493fea3
4 changed files with 111 additions and 3 deletions

View File

@ -5,6 +5,15 @@
* [Two scoops of Django](http://twoscoopspress.com/). Ce livre couvre les principaux concepts de Django. L'avantage est qu'on peut l'ouvrir au hasard et lire un chapitre sans devoir lire les précédents. Ce livre-ci ne constitue cependant pas un tutorial pour développer une application Django *from-scratch*.
* [Django Design Patterns](https://www.packtpub.com/web-development/django-design-patterns-and-best-practices), d'Arun Ravindran.
## Sur le Web
* [Books by Agiliq](https://books.agiliq.com/en/latest/README.html) - Ils ont de tout, dont certains particulièrement utiles:
* [Django Admin Cookbook](https://books.agiliq.com/projects/django-admin-cookbook/) - pour Django 2.0, mais toujours d'actualité.
* [Django ORM](https://books.agiliq.com/projects/django-orm-cookbook/) - Idem (Django 2.0), mais cible précisément les fonctions de l'ORM.
* [Building APIs with Django and Django Rest Framework](http://books.agiliq.com/projects/django-api-polls-tutorial/), qu'on n'aborde pas ici ;-)
Et plein d'autres sucreries.
## Sites
* [Sam & Max](http://sametmax.com)

View File

@ -0,0 +1,18 @@
(c/c Ced' - 2020-01-24)
Ça y est, j'ai fait un test sur mon portable avec docker et cookiecutter pour django.
D'abords, après avoir installer docker-compose et les dépendances sous debian, tu dois t'ajouter dans le groupe docker, sinon il faut être root pour utiliser docker.
Ensuite, j'ai relancé mon pc car juste relancé un shell n'a pas suffit pour que je puisse utiliser docker avec mon compte.
Bon après c'est facile, un petit virtualenv pour cookiecutter, suivit d'une installation du template django.
Et puis j'ai suivi sans t https://cookiecutter-django.readthedocs.io/en/latest/developing-locally-docker.html
Alors, il télécharge les images, fait un petit update, installe les dépendances de dev, install les requirement pip ...
Du coup, ça prend vite de la place:
image.png
L'image de base python passe de 179 à 740 MB. Et là j'en ai pour presque 1,5 GB d'un coup.
Mais par contre, j'ai un python 3.7 direct et postgres 10 sans rien faire ou presque.

View File

@ -70,6 +70,8 @@ A partir de maintenant, on peut accéder à nos propriétés de la manière suiv
Remarque: si, dans une classe A, plusieurs relations sont liées à une classe B, Django ne saura pas à quoi correspondra la relation inverse. Pour palier à ce problème et pour gagner en cohérence, on fixe alors une valeur à l'attribut `related_name`.
=== Querysets et managers
NOTE : faudra sortir les queryset du chapitre...
* http://stackoverflow.com/questions/12681653/when-to-use-or-not-use-iterator-in-the-django-orm
* https://docs.djangoproject.com/en/1.9/ref/models/querysets/#django.db.models.query.QuerySet.iterator
@ -81,8 +83,28 @@ L'ORM de Django (et donc, chacune des classes qui composent votre modèle) propo
* Les querysets, qui permettent de filtrer des ensembles ou sous-ensemble d'objets. Les querysets peuvent s'imbriquer, pour ajouter
d'autres filtres à des filtres existants.
Ces deux propriétés vont de paire; par défaut, chaque classe de votre modèle propose un attribut `objects`, qui correspond à un manager (ou un gestionnaire, si vous préférez). Ce gestionnaire constitue l'interface par laquelle vous accéderez à la base de données. Mais pour cela, vous aurez aussi besoin d'appliquer certains requêtes ou filtres. Et pour cela, vous aurez besoin des `querysets`, qui consistent en des ... ensembles de requêtes :-).
Ces deux propriétés vont de paire; par défaut, chaque classe de votre modèle propose un attribut `objects`, qui correspond
à un manager (ou un gestionnaire, si vous préférez). Ce gestionnaire constitue l'interface par laquelle vous accéderez à la base de données. Mais pour cela, vous aurez aussi besoin d'appliquer certains requêtes ou filtres. Et pour cela, vous aurez besoin des `querysets`, qui consistent en des ... ensembles de requêtes :-).
Si on veut connaître la requête SQL sous-jacente à l'exécution du queryset, il suffit d'appeler la fonction str() sur la propriété `query`:
[source,python]
----
queryset = Wishlist.objects.all()
print(queryset.query)
----
Conditions AND et OR sur un queryset
Pour un `AND`, il suffit de chaîner les conditions. ** trouver un exemple ici ** :-)
Mais en gros : bidule.objects.filter(condition1, condition2)
Il existe deux autres options : combiner deux querysets avec l'opérateur `&` ou combiner des Q objects avec ce même opérateur.
Soit encore combiner des filtres:
[source,python]
----
from core.models import Wish
@ -92,8 +114,35 @@ Wish.objects.filter(name__icontains="test").filter(name__icontains="too") <2>
----
<1> Ca, c'est notre manager.
<2> Et là, on chaîne les requêtes pour composer une recherche sur tous les souhaits dont le nom contient (avec une casse insensible) la chaîne "test" et dont le nom contient la chaîne "too".
Pour un 'OR', on a deux options :
. Soit passer par deux querysets, typiuqment `queryset1 | queryset2`
. Soit passer par des `Q objects`, que l'on trouve dans le namespace `django.db.models`.
[source,python]
----
from django.db.models import Q
condition1 = Q(...)
condition2 = Q(...)
bidule.objects.filter(condition1 | condition2)
----
L'opérateur inverse (_NOT_)
Idem que ci-dessus : soit on utilise la méthode `exclude` sur le queryset, soit l'opérateur `~` sur un Q object;
Ajouter les sujets suivants :
. Prefetch
. select_related
=== Aggregate vs. Annotate
https://docs.djangoproject.com/en/3.1/topics/db/aggregation/
=== Metamodèle
@ -115,6 +164,8 @@ class Wish(models.Model):
----
<1> On définit un ordre par défaut, directement au niveau du modèle. Cela ne signifie pas qu'il ne sera pas possible de modifier cet ordre (la méthode `order_by` existe et peut être chaînée à n'importe quel queryset). D'où l'intérêt de tester ce type de comportement, dans la mesure où un `top 1` dans votre code pourrait être modifié simplement par cette petite information.
Pour sélectionner un objet au pif : `return Category.objects.order_by("?").first()`
Les propriétés de la classe Meta les plus utiles sont les suivates:
* `ordering` pour spécifier un ordre de récupération spécifique.

View File

@ -232,4 +232,34 @@ def wishlists_list():
----
=== Contexts Processors
Un `context processor` permet d'ajouter des informations par défaut à un contexte (le dictionnaire qu'on passe de la vue au template).
L'idée est d'ajouter une fonction à un module Python à notre projet, puis de le référencer parmi
les CONTEXT_PROCESSORS de nos paramètres généraux. Cette fonction doit peupler un dictionnaire, et les clés de ce dictionnaire seront
directement ajoutées à tout autre dictionnaire/contexte passé à une vue. Par exemple:
(cf. https://stackoverflow.com/questions/60515797/default-context-for-all-pages-django[StackOverflow] - à retravailler)
[source,python]
----
from product.models import SubCategory, Category
def add_variable_to_context(request):
return {
'subCategories': SubCategory.objects.order_by('id').all(),
'categories': Category.objects.order_by("id").all(),
}
----
[source,python]
----
'OPTIONS': {
'context_processors': [
....
'core.context_processors.add_variable_to_context',
....
],
},
----