[PYTHON] Développement piloté par les tests avec Django Partie 3

Développement piloté par les tests avec Django Partie 3

Ceci est une note d'apprentissage pour comprendre le développement piloté par les tests (TDD) dans Django.

Les références sont [** Test-Driven Development with Python: Obey the Testing Goat: Using Django, Selenium, and JavaScript (English Edition) 2nd Edition **](https://www.amazon.co.jp/dp/B074HXXXLS Nous allons procéder à l'apprentissage basé sur / ref = dp-kindle-redirect? _ Encoding = UTF8 & btkr = 1).

Dans ce livre, nous effectuons des tests fonctionnels en utilisant la série Django 1.1 et FireFox, mais cette fois nous allons effectuer des tests fonctionnels sur la série Djagno 3 et Google Chrome. J'ai également apporté quelques modifications personnelles (comme changer le nom du projet en Config), mais il n'y a pas de changements majeurs.

⇒⇒ Cliquez ici pour Partie 1 - Chapitre 1 ⇒⇒ Cliquez ici pour Partie 2-Chapitre 2

Part1. The Basics of TDD and Django

Capter3. Testing as Simple Home Page with Unit Tests

Dans le chapitre 2, nous avons écrit un test fonctionnel en utilisant ʻunittest.TestCase` et avons testé s'il y avait un "To-Do" dans le titre de la page. Cette fois, nous allons réellement démarrer l'application et exécuter TDD.

Our First Django App, and Our First Unit Test

Django prend la forme de la construction de plusieurs applications sous un même projet. Créons tout de suite une application Django. Ici, nous allons créer une application nommée ** lists **.

$ python manage.py startapp lists

Unit Tests, and How They Differ from Functional Tests

Les tests fonctionnels testent l'application de l'extérieur (du point de vue de l'utilisateur) pour voir si elle fonctionne correctement. Les tests unitaires testent si l'application fonctionne de l'intérieur (du point de vue du développeur). Le TDD est nécessaire pour couvrir les tests fonctionnels et les tests unitaires, et la procédure de développement est la suivante.

** step1. ** Rédiger un test fonctionnel (expliquant les nouvelles fonctionnalités du point de vue de l'utilisateur).

** step2. ** Si le test fonctionnel échoue, réfléchissez à la façon d'écrire le code pour réussir le test (ne l'écrivez pas soudainement). Ajoutez un test unitaire pour définir le comportement de votre code.

** step3. ** Si le test unitaire échoue, écrivez le code d'application minimum que le test unitaire passera.

** step4. ** Répétez les étapes 2 et 3 pour enfin vérifier si le test fonctionnel réussit.

Unit Testing in Django

J'écrirai le test de la vue de la page d'accueil dans lists / tests.py. Vérifions ici d'abord.

# lists/tests.py

from django.test import TestCase

# Create your tests here.

En regardant cela, j'ai trouvé que je pouvais écrire un test unitaire en utilisant la classe TestCase fournie par Django. djagno.test.TestCase est une extension du module standard ʻunittest.TestCase` utilisé dans le test fonctionnel. J'écrirai un test unitaire à titre d'essai.

# lists/tests.py

from django.test import TestCase


class SmokeTest(TestCase):

    def test_bad_maths(self):
        self.assertEqual(1 + 1, 3)

Django a une fonctionnalité de test runner qui recherche et exécute des tests pour chaque application. Lançons le testeur de Django.

$ python manage.py test

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F
======================================================================
FAIL: test_bad_maths (lists.tests.SmokeTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\--your_pass--\django-TDD\lists\tests.py", line 9, in test_bad_maths
    self.assertEqual(1 + 1, 3)
AssertionError: 2 != 3

----------------------------------------------------------------------
Ran 1 test in 0.005s

FAILED (failures=1)
Destroying test database for alias 'default'...

J'ai pu confirmer que lists / tests.py a été exécuté et a échoué. Je vais m'engager ici.

$ git status
$ git add lists
$ git commit -m "Add app for lists, with deliberately failing unit test"

Django's MVC, URLs, and View Functions

Django doit définir ce qu'il faut faire avec une URL particulière. Le flux de travail Django ressemble à ceci:

  1. HTTP / requête arrive à une URL spécifique

  2. Puisque la règle a été déterminée quelle vue doit être exécutée pour HTTP / requête, exécutez la vue selon la règle.

  3. View traite la demande et renvoie HTTP / réponse.

Par conséquent, nous avons deux choses à faire:

  1. Est-il possible de résoudre l'URL entre l'URL et la vue?

  2. View peut-il modifier le code HTML qui peut passer le test fonctionnel?

Maintenant, ouvrons lists / tests.py et écrivons un petit test.

# lists/tests.py

from django.urls import resolve  #ajouter à
from django.test import TestCase
from lists.views import home_page  #ajouter à

class HomePageTest(TestCase):

    def test_root_url_resolve_to_home_page_view(self):
        found = resolve('/')
        self.assertEqual(found.func, home_page)

django.urls.resolve est un module de résolution des URL utilisées en interne par django. from lists.views import home_page est la vue à décrire ensuite. Vous pouvez voir que cela est décrit ci-dessous. Testons-le.

$ python manage.py test

System check identified no issues (0 silenced).
E
======================================================================
ERROR: lists.tests (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: lists.tests
Traceback (most recent call last):
  File "C:\--your_user_name--\AppData\Local\Programs\Python\Python37\lib\unittest\loader.py", line 436, in _find_test_path
    module = self._get_module_from_name(name)
  File "C:\--your_user_name--\AppData\Local\Programs\Python\Python37\lib\unittest\loader.py", line 377, in _get_module_from_name
    __import__(name)
  File "C:\--your_path--\django-TDD\lists\tests.py", line 5, in <module>
    from lists.views import home_page
ImportError: cannot import name 'home_page' from 'lists.views' (C:\Users\--your_path--\django-TDD\lists\views.py)


----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

Une erreur d'importation est apparue. En regardant le contenu, cela me dit que home_page ne peut pas être importé de lists.views. Maintenant, écrivons home_page dans lists.views.

# lists/views.py

from django.shortcuts import render

home_page = None

Cela ressemble à une blague, mais cela devrait résoudre l '«Erreur d'importation». Rappelez-vous que TDD écrit le plus petit code pour résoudre une erreur.

Testons-le à nouveau.

$ python manage.py test

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
E
======================================================================
ERROR: test_root_url_resolve_to_home_page_view (lists.tests.SmokeTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\--your_path--\django-TDD\lists\tests.py", line 10, in test_root_url_resolve_to_home_page_view
    found = resolve('/')
  File "C:\--your_path--\django-TDD\venv-tdd\lib\site-packages\django\urls\base.py", line 25, in resolve
    return get_resolver(urlconf).resolve(path)
  File "C:\--your_path--\django-TDD\venv-tdd\lib\site-packages\django\urls\resolvers.py", line 575, in resolve
    raise Resolver404({'tried': tried, 'path': new_path})
django.urls.exceptions.Resolver404: {'tried': [[<URLResolver <URLPattern list> (admin:admin) 'admin/'>]], 'path': ''}

----------------------------------------------------------------------
Ran 1 test in 0.005s

FAILED (errors=1)
Destroying test database for alias 'default'...

Bien sûr, l '«erreur d'importation» a été résolue, mais le test a de nouveau échoué. Si vous cochez Traceback, vous pouvez voir que Django renvoie une erreur 404 même si résoudre résout '/'. Cela signifie que Django n'a pas été en mesure de résoudre `` '/' '.

urls.py

Django a urls.py qui mappe les URL aux vues. config / urls.py sera l'urls.py principale. Vérifions ici.

# config/urls.py

"""config URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]

Si vous vérifiez le contenu, vous trouverez comment écrire un mappage d'URL appelé «" config URL Configuration "», alors reportez-vous-y. Cette fois, ajoutons le mappage entre «/» «et« home_page »aux« motifs d'url »en écrivant des vues Funciton. De plus, ʻadmin / ʻn'est pas encore utilisé, alors commentez-le.

# config/urls.py

from django.contrib import admin
from django.urls import path
from lists import views


urlpatterns = [
    # path('admin/', admin.site.urls),  #Commenter
    path('', views.home_page, name='home')
]

La cartographie est terminée. Faites un test.

$ python manage.py test
[...]
TypeError: view must be a callable or a list/tuple in the case of include().

J'ai ajouté le mappage d'URL pour que l'erreur 404 soit résolue, mais j'ai eu une erreur de type. Il semble que cela soit dû au fait que lorsque vous appelez home_page depuis lists.view, rien n'est renvoyé avec home_page = None. Corrigeons cela en éditant lists / views.py.

# lists/views.py

from django.shortcuts import render

def home_page():
    pass

Je vais le tester.

$ python manage.py test

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.003s

OK
Destroying test database for alias 'default'...

J'ai réussi le test unitaire. Je vais m'engager ici.

$ git add .
$ git status
$ git commit -m "First unit test and url mapping, dummy view"

Nous réécrirons lists / tests.py afin de pouvoir tester si les listes / vues.py actuelles renvoient réellement du HTML.

# lists/tests.py

from django.urls import resolve
from django.test import TestCase
from django.http import HttpRequest

from lists.views import home_page


class HomePageTest(TestCase):

    def test_root_url_resolve_to_home_page_view(self):
        found = resolve('/')
        self.assertEqual(found.func, home_page)

    def test_home_page_returns_current_html(self):  #ajouter à
        request = HttpRequest()
        response = home_page(request)
        html = response.content.decode('utf8')
        self.assertTrue(html.startswith.('<html>'))
        self.assertIn('<title>To-Do lists</title>', html)
        self.assertTrue(html.endwith('</html>'))

test_root_url_resolve_to_home_page_view vérifie si le mappage d'URL est correct, Je vérifie si le bon HTML peut être retourné avec test_home_page_returns_current_html. Nous avons ajouté un nouveau test unitaire, donc testons-le immédiatement.

$ python manage.py test

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
E.
======================================================================
ERROR: test_home_page_returns_current_html (lists.tests.SmokeTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\--your_path--\django-TDD\lists\tests.py", line 18, in test_home_page_returns_current_html
    response = home_page(request)
TypeError: home_page() takes 0 positional arguments but 1 was given

----------------------------------------------------------------------
Ran 2 tests in 0.005s

FAILED (errors=1)
Destroying test database for alias 'default'...

J'ai un TypeError. Quand je vérifie le contenu, il dit home_page () prend 0 argument positionnel mais 1 a été donné. Vous pouvez voir que la définition de home_page () ne spécifie aucun argument (0 arguments positionnels), mais c'est étrange avec les arguments donnés ( 1 a été donné).

Je voudrais donc réécrire lists / views.py.

# lists/views.py

from django.shortcuts import render


def home_page(request):  #Changement
    pass

Ajout de l'argument request à la fonction home_page (). Testons avec ça.

$ python manage.py test

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
E.
======================================================================
ERROR: test_home_page_returns_current_html (lists.tests.SmokeTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\--your_path--\django-TDD\lists\tests.py", line 19, in test_home_page_returns_current_html
    html = response.content.decode('utf8')
AttributeError: 'NoneType' object has no attribute 'content'

----------------------------------------------------------------------
Ran 2 tests in 0.005s

FAILED (errors=1)
Destroying test database for alias 'default'...

Le TypeError a été résolu, mais la prochaine fois que j'obtiens un ʻAttributeError. Puisqu'il dit que l'objet 'NoneType' n'a pas d'attribut'content', il semble que la cause en soit que la valeur de retour de home_page (request) soit None. Modifiez lists / views.py.

# lists/views.py

from django.shortcuts import render
from django.http import HttpResponse  #ajouter à


def home_page(request):
    return HttpResponse()

Correction du retour de django.http.HttpResponse. Testons-le.

$ python manage.py test

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F.
======================================================================
FAIL: test_home_page_returns_current_html (lists.tests.SmokeTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\--your_path--\django-TDD\lists\tests.py", line 20, in test_home_page_returns_current_html
    self.assertTrue(html.startswith('<html>'))
AssertionError: False is not true

----------------------------------------------------------------------
Ran 2 tests in 0.005s

FAILED (failures=1)
Destroying test database for alias 'default'...

ʻAttribute Error a été résolu et ʻAssertion Error s'est produite. Vous pouvez voir que le message «False is not ture» s'affiche car «html.startwith ('')« est False. Modifiez lists / views.py.

# lists/views.py

from django.shortcuts import render
from django.http import HttpResponse


def home_page(request):
    return HttpResponse('<html>')  #Changement
$ python manage.py test

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F.
======================================================================
FAIL: test_home_page_returns_current_html (lists.tests.SmokeTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\--your_path--\django-TDD\lists\tests.py", line 21, in test_home_page_returns_current_html
    self.assertIn('<title>To-Do lists</title>', html)
AssertionError: '<title>To-Do lists</title>' not found in '<html>'

----------------------------------------------------------------------
Ran 2 tests in 0.005s

FAILED (failures=1)
Destroying test database for alias 'default'...

C'est aussi une «erreur d'assertion». On dit que `` To-Do lists </ title> '' ne peut pas être trouvé. Modifiez lists / views.py.</p> <pre><code class="language-python"># lists/views.py from django.shortcuts import render from django.http import HttpResponse def home_page(request): return HttpResponse('<html><title>To-Do lists</title>') #Changement </code></pre> <pre><code class="language-sh">$ python manage.py test Creating test database for alias 'default'... System check identified no issues (0 silenced). F. ====================================================================== FAIL: test_home_page_returns_current_html (lists.tests.SmokeTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\--your_path--\django-TDD\lists\tests.py", line 22, in test_home_page_returns_current_html self.assertTrue(html.endswith('</html>')) AssertionError: False is not true ---------------------------------------------------------------------- Ran 2 tests in 0.013s FAILED (failures=1) Destroying test database for alias 'default'... </code></pre> <p>C'est aussi une «erreur d'assertion». On dit que `` '</ html>' 'ne peut pas être trouvé. Modifiez lists / views.py.</p> <pre><code class="language-python"># lists/views.py from django.shortcuts import render from django.http import HttpResponse def home_page(request): return HttpResponse('<html><title>To-Do lists</title></html>') #Changement </code></pre> <p>Cela devrait enfin fonctionner.</p> <pre><code class="language-sh">$ python manage.py test Creating test database for alias 'default'... System check identified no issues (0 silenced). .. ---------------------------------------------------------------------- Ran 2 tests in 0.004s OK Destroying test database for alias 'default'... </code></pre> <p>Ça s'est bien passé. Maintenant que le test unitaire a réussi, démarrons le serveur de développement, puis exécutons le test fonctionnel.</p> <pre><code class="language-sh">#Lancer le serveur de développement $ python manage.py runserver #Lancer une autre cmd et exécuter un test fonctionnel $ python functional_tests.py DevTools listening on ws://127.0.0.1:51108/devtools/browser/9d1c6c55-8391-491b-9b14-6130c3314bba F ====================================================================== FAIL: test_can_start_a_list_and_retrieve_it_later (__main__.NewVisitorTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "functional_tests.py", line 21, in test_can_start_a_list_and_retrieve_it_later self.fail('Finish the test!') AssertionError: Finish the test! ---------------------------------------------------------------------- Ran 1 test in 7.244s FAILED (failures=1) </code></pre> <p>Le test fonctionnel est FAILED, car j'ai utilisé «.fail» dans «unittest.TestCase» pour m'assurer qu'une erreur se produit même si le test réussit. Par conséquent, vous pouvez voir que le test fonctionnel a réussi!</p> <p>Engageons-nous.</p> <pre><code class="language-sh">$ git add . $ git commit -m "Basic view now return minimal HTML" </code></pre> <h4>Résumé du chapitre 3</h4> <p>Assurez-vous de l'avoir couvert jusqu'à présent.</p> <ul> <li> <p>L'application Django a démarré.</p> </li> <li> <p>J'ai utilisé le lanceur de test unitaire de Django.</p> </li> </ul> <p>--Je comprends la différence entre un test fonctionnel et un test unitaire.</p> <p>--Création d'une vue à l'aide des objets de requête et de réponse de Django</p> <ul> <li>Retourné HTML de base.</li> </ul> <p>J'ai pu confirmer le processus de création de fonctions en tournant le test unitaire et le cycle d'ajout / correction de code.</p> <!-- ENDDDDDDDDDDDDDDDDDDDDDDDDDDDDD --> <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- post_new_ui_horiz --> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-5469278205356604" data-ad-slot="4209814965" data-ad-format="auto" data-full-width-responsive="true"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> <div style="margin-top: 30px;"> <div class="link-top" style="margin-top: 1px;"></div> <p> <font size="4">Recommended Posts</font> <!-- BEGIN LINK ************************* --> <div style="margin-top: 10px;"> <a href="/fr/0057b55c8ba763bda6ca">Développement piloté par les tests avec Django Partie 3</a> </div> <div style="margin-top: 10px;"> <a href="/fr/148b42f070be478f6e23">Développement piloté par les tests avec Django Partie 4</a> </div> <div style="margin-top: 10px;"> <a href="/fr/25668d8d53f0c099388f">Développement piloté par les tests avec Django Partie 6</a> </div> <div style="margin-top: 10px;"> <a href="/fr/58dc509e8f681da73199">Développement piloté par les tests avec Django Partie 2</a> </div> <div style="margin-top: 10px;"> <a href="/fr/dd7abd24961250208c7c">Développement piloté par les tests avec Django Partie 1</a> </div> <div style="margin-top: 10px;"> <a href="/fr/f431c13531ced5b3d2f3">Développement piloté par les tests avec Django Partie 5</a> </div> <div style="margin-top: 10px;"> <a href="/fr/52335515344b181bed31">Démarrage du développement piloté par les tests avec PySide & Pytest</a> </div> <div style="margin-top: 10px;"> <a href="/fr/0e15f6c150caa13ca34c">Résumé du développement avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/3b3265d745aef36f26ff">Test Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/ae41a2c1f49bb920cf58">[Test Driven Development (TDD)] Chapitre 21 Résumé</a> </div> <div style="margin-top: 10px;"> <a href="/fr/96bedd0b9d9a0ed9b01b">Développement d'applications à l'aide de SQLite avec Django (PTVS)</a> </div> <div style="margin-top: 10px;"> <a href="/fr/218b4a4918cf4fb2079d">Django a commencé la partie 1</a> </div> <div style="margin-top: 10px;"> <a href="/fr/344666a0d77503b05b1b">Découvrez la partie I «Monnaie multinationale» du livre «Test Driven Development» avec Python</a> </div> <div style="margin-top: 10px;"> <a href="/fr/4f59f154b7a4b111fe0d">Internationalisation avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/5a4495e4df24d395bec4">Django a commencé la partie 4</a> </div> <div style="margin-top: 10px;"> <a href="/fr/ab7f0eeeaec0e60d6b92">CRUD avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/d616a74f931babae4566">Premier développement Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/1ab36e3d5365e8ca2942">Créez des données de test comme ça avec Python (partie 1)</a> </div> <div style="margin-top: 10px;"> <a href="/fr/60bc24dba80688d5d03a">[Python] Créer un environnement de développement Django avec Docker</a> </div> <div style="margin-top: 10px;"> <a href="/fr/932b14dee0ec2efbf1a7">Django Getting Started Part 2 avec eclipse Plugin (PyDev)</a> </div> <div style="margin-top: 10px;"> <a href="/fr/943093d15db9a55e7b4c">Créer un environnement de développement Django à l'aide de Doker Toolbox</a> </div> <div style="margin-top: 10px;"> <a href="/fr/005109fa4d9ad9736eb1">Authentifier Google avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/03c5bd710221a8145dbf">Django 1.11 a démarré avec Python3.6</a> </div> <div style="margin-top: 10px;"> <a href="/fr/03c6ddf42e6edd584a07">Jugement des nombres premiers avec Python</a> </div> <div style="margin-top: 10px;"> <a href="/fr/06c52ecfd3c40cbbe522">Télécharger des fichiers avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/1613b2ac40caad14d62f">Renforcez avec le test de code ⑦</a> </div> <div style="margin-top: 10px;"> <a href="/fr/201d278ee52e81cf4eee">Sortie PDF avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/20c4b459b9fc52aef062">Renforcez avec le test de code ⑨</a> </div> <div style="margin-top: 10px;"> <a href="/fr/262590c2d1b727052aea">Renforcez avec le test de code ③</a> </div> <div style="margin-top: 10px;"> <a href="/fr/271b38ef2c6610f40929">Sortie Markdown avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/42d6029e8f8eec510118">Utiliser Gentelella avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/4c9edec8fbefb3116bf6">Twitter OAuth avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/58052e820a384d6dcb47">Renforcez avec le test de code ⑤</a> </div> <div style="margin-top: 10px;"> <a href="/fr/5df4bde4435d9d0b2a1a">Renforcez avec le test de code ④</a> </div> <div style="margin-top: 10px;"> <a href="/fr/6e044550435796ef09c5">Premiers pas avec Django 1</a> </div> <div style="margin-top: 10px;"> <a href="/fr/715cdd6c2830e2aca0f6">Jugement des nombres premiers avec python</a> </div> <div style="margin-top: 10px;"> <a href="/fr/82454eaedbf94273c4f1">Envoyer des e-mails avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/897221c051bd673471cb">bac à sable avec neo4j partie 10</a> </div> <div style="margin-top: 10px;"> <a href="/fr/8da746e150d1e0947107">Application Web réalisée avec Python3.4 + Django (Construction de l'environnement Part.1)</a> </div> <div style="margin-top: 10px;"> <a href="/fr/8f94095a1e58e2d5cb21">Téléchargement de fichiers avec django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/9d3e3db6706dd69407c6">Renforcez avec le test de code ②</a> </div> <div style="margin-top: 10px;"> <a href="/fr/abaf2a920ce60339a87f">Utilisez LESS avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/b98ee1d1aa59fc12866e">La mutualisation mécanise avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/c9dbc320a0e0e84093da">Utiliser MySQL avec Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/d14cc2b97ea595a13045">Renforcez avec le test de code ①</a> </div> <div style="margin-top: 10px;"> <a href="/fr/dde20a965e212ab449b2">Créez un environnement de développement avec Poetry Django Docker Pycharm</a> </div> <div style="margin-top: 10px;"> <a href="/fr/ecae39fe75b412d44e89">[Memo] Environnement de développement Django</a> </div> <div style="margin-top: 10px;"> <a href="/fr/ed64190a12a4498b9446">Articles permettant le développement de systèmes avec Django (Python) _Introduction</a> </div> <div style="margin-top: 10px;"> <a href="/fr/edb561ceae1c4abdd16a">Django à partir d'aujourd'hui</a> </div> <div style="margin-top: 10px;"> <a href="/fr/f696723ee7ac9c3796cd">Premiers pas avec Django 2</a> </div> <div style="margin-top: 10px;"> <a href="/fr/fbf614250f13b50dac7e">Renforcez avec le test de code ⑧</a> </div> <div style="margin-top: 10px;"> <a href="/fr/fdd86d6166533c1070ef">Renforcez avec le test de code ⑨</a> </div> <div style="margin-top: 10px;"> <a href="/fr/1665099685f9a05820ce">Tutoriel pour faire du développement piloté par les tests (TDD) avec Flask-2 Decorators</a> </div> <div style="margin-top: 10px;"> <a href="/fr/242367a83c313a5e46bf">Créez un environnement de développement Django avec Docker! (Docker-compose / Django / postgreSQL / nginx)</a> </div> <div style="margin-top: 10px;"> <a href="/fr/371881a6b8ecfa768606">[Memo] Construire un environnement de développement pour Django + Nuxt.js avec Docker</a> </div> <div style="margin-top: 10px;"> <a href="/fr/82678e1cd59c925846b4">[Django] Créez rapidement un environnement de développement de conteneur Django (Docker) avec PyCharm</a> </div> <div style="margin-top: 10px;"> <a href="/fr/8b55d1e134f29b8a8dcd">Créez une application de tableau d'affichage à partir de zéro avec Django. (Partie 2)</a> </div> <!-- END LINK ************************* --> </p> </div> </div> </div> <div class="footer text-center" style="margin-top: 40px;"> <!-- <p> Licensed under cc by-sa 3.0 with attribution required. </p> --> </div> <script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.1.2/build/highlight.min.js"></script> <script> $(document).ready(function() { var cfg_post_height = 60; var cfg_per = 0.51; var ads_obj = $('<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-5469278205356604" data-ad-slot="7950405964"></ins>'); $('pre code').each(function(i, e) {hljs.highlightBlock(e)}); function getDocumentOffsetPosition( el ) { var _x = 0; var _y = 0; while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) { _x += el.offsetLeft - el.scrollLeft; _y += el.offsetTop - el.scrollTop; el = el.offsetParent; } return { top: _y, left: _x }; } if ( $( "#article202011" ).length ) { var h1_pos = getDocumentOffsetPosition($('h1')[0]); var footer_pos = getDocumentOffsetPosition($('.link-top')[0]); var post_distance = footer_pos.top - h1_pos.top; // console.log('h1_pos: '+ h1_pos.top); // console.log(cfg_post_height) if((post_distance/h1_pos.top)>=cfg_post_height) { // console.log('tesssssssssssssssssssssssssssssssss'); $( ".container p" ).each(function( index ) { var p_tag_pos = $(this).position().top; var dis = p_tag_pos - h1_pos.top; var per = dis/post_distance; if(per>cfg_per) { ads_obj.insertAfter($(this)); (adsbygoogle = window.adsbygoogle || []).push({}); console.log( index + ": " + $( this ).text() ); return false; } }); } } }); </script> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> <!-- ads --> <script data-ad-client="ca-pub-5469278205356604" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" type="d7540fe192d881abe59fcf57-text/javascript"></script> <!-- end ads --> </body> </html>