2020-05-10: Création
2020-05-11: Ajout SASS
2020-05-12: Ajout foundation-sites CSS Framework
2020-05-15: ReactJS 'App.js & class App render'
2020-05-16: Ajout de Compass SASS Framework
2020-05-17: Nouvelle structure de dossiers
2020-05-17: Utilisation
2021-10-25: Séparation avec_virtualenv et avec_pipenv
2021-10-25: Notes sur la configuration du fichier settings.py
Cette procédure est écrite à l'occasion de la refonte du projet sport reporting.
En plus d'utiliser pipenv j'y ajoute webpack afin d'intégrer sass et foundation zurb depuis yarnpkg sous debian 10 bullseye (testing).
Cette méthode est de plusieurs jours de recherche et de test de différentes sources:
Donc à utiliser pour les petites applications, ne nécessitant pas un gros fichier JS (>200ko) sinon, il faut utiliser le code spliting https://webpack.js.org/plugins/split-chunks-plugin/
# création du dossier projet: cd ~/dev/ mkdir sport cd sport
git init touch .gitignore
Dans le fichier .gitignore mettre les exclusions du standard de github:
git add -A git commit -m "build(init): Main app directory"
Le dossier venv est créé par PyCharm Pro
lors de la définition du projet.
Cette commande permet d'activer cet environnement virtuel:
$ source venv/bin/activate
On peut contrôler le contenu de l'environnement virtuel:
$ pip list Package Version ---------- ------- asgiref 3.4.1 Django 3.2.8 pip 21.3.1 pytz 2021.3 setuptools 57.0.0 sqlparse 0.4.2 wheel 0.36.2
Cette commande permet de créer l'environnement virtuel et de l'activer:
pipenv shell Creating a virtualenv for this project… Pipfile: /home/jc/dev/sport/Pipfile Using /usr/bin/python3 (3.8.2) to create virtualenv… ⠴ Creating virtual environment...
Installation de django et modules aux. depuis pipenv:
pipenv install django Pillow django-crispy-forms crispy-forms-foundation ls -lh -rw-r--r-- 1 jc jc 220 mai 10 11:46 Pipfile -rw-r--r-- 1 jc jc 4,3K mai 10 11:47 Pipfile.lock
Git:
git add -A git commit -m "build(init): Python virtual environnement."
django-admin startproject . config_prj
Organisation des dossiers du projet:
tree
.
├── config_prj
│ ├── asgi.py
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── Pipfile
└── Pipfile.lock
Git:
git add -A git commit -m "build(django): Django init project."
python manage.py startapp reporting
Activation de l'app
ALLOWED_HOSTS = ["127.0.0.1", "192.168.1.2", "192.168.1.3", "192.168.1.4"] INSTALLED_APPS = [ [...] # 'users.apps.UsersConfig', #user management 'reporting.apps.ReportingConfig', #main app 'crispy_forms', #addon for load django form ] TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ os.path.join(BASE_DIR, 'templates'), ], [...] LANGUAGE_CODE = 'fr-fr'
PyCharm Pro
, le paramétrage du dossier templates
est déjà fait. Il faut juste créer ce dossier à la racine du projet Django.
Structure des dossiers :
. ├── config_prj │ ├── asgi.py │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ ├── views.py │ └── wsgi.py ├── manage.py ├── Pipfile ├── Pipfile.lock └── reporting ├── admin.py ├── apps.py ├── __init__.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py └── views.py
Git:
git add -A git commit -m "build(django): Django reporting app."
Dans le dossier racine du projet config_prj, créer le dossier template:
mkdir templates
Dans le dossier de configuration du projet, créer le fichier views.py:
from django.shortcuts import render def index(request): return render(request, "index.html")
Dans le dossier template créer le fichier index.html
<html> <head> <title>Demo</title> </head> <body> <h1>Hello World!</h1> </body> </html>
Dans le fichier urls.py, ajouter la vue:
from django.contrib import admin from django.urls import path from . import views urlpatterns = [ path('', views.index), path('admin/', admin.site.urls), ]
Dans le fichier settings.py ajouter l'accès au dossier templates:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], [...]
A ce stade on peut contrôler l'enchaînement des urls.py/views.py/index.html:
python manage.py runserver
Structure :
. ├── config_prj │ ├── asgi.py │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ ├── views.py │ └── wsgi.py ├── db.sqlite3 ├── manage.py ├── Pipfile ├── Pipfile.lock ├── reporting │ ├── admin.py │ ├── apps.py │ ├── __init__.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py └── templates └── index.html
Git:
git add -A git commit -m "build(django): Django hello world."
A la racine du projet, créer les dossiers static/css avec main.css
h1 { color: red; }
Dans template/index.html ajout en en-tête load static et le lien stylesheet:
{% load static %} <html> <head> <title>Demo</title> <link rel="stylesheet" href="{% static 'css/main.css' %}"/> </head> <body> <h1>Hello World!</h1> </body> </html>
En début du fichier settings.py ajouter :
import os
En fin du fichier settings.py ajouter :
STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static') ]
Visu du rendu avec le css sans le transpileur SASS:
Git:
git add -A git commit -m "build(django): CSS without SASS transpiler."
Webpack est utiliser pour générer ou transpiler du code dans un autre format de code:
Exemple, le langage SASS vers CSS et JSX en JS.
Ce placer dans le dossier static du projet :
yarnpkg init yarn init v1.22.4 question name (django_static): question version (1.0.0): question description ("django with webpack integration in static folder"): django with webpack integration in static folder question entry point (index.js): question repository url: question author (JC_onLine): question license (MIT): question private: success Saved package.json
yarnpkg add -D webpack webpack-cli @babel/core @babel/preset-env @babel/preset-react babel-loader style-loader css-loader sass sass-loader node-sass [...] info Direct dependencies ├─ @babel/core@7.9.6 ├─ @babel/preset-env@7.9.6 ├─ @babel/preset-react@7.9.4 ├─ babel-loader@8.1.0 ├─ css-loader@3.5.3 ├─ node-sass@4.14.1 ├─ sass-loader@8.0.2 ├─ sass@1.26.5 ├─ style-loader@1.2.1 ├─ webpack-cli@3.3.11 └─ webpack@4.43.0 [...]
Toujours dans le dossier static du projet, créer le fichier webpack.config.js:
const path = require('path') module.exports = { entry: { app: './src/index.js' }, watch: true, devtool: 'source-map', output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: ['babel-loader'] } ] }, resolve: { extensions: [ '.js' ] } }
Dans le dossier static, créer le dossier src avec index.js dedans:
const x = "this is a test alert"; alert(x);
et ajouter le lien js à index.html
{% load static %} <html> <head> <title>Demo</title> <link rel="stylesheet" href="{% static 'css/main.css' %}"/> </head> <body> <h1>Hello World!</h1> <script src="{% static 'dist/app.bundle.js' %}"></script> </body> </html>
Paramétrage du fichier package.json (en dessous de “main”: “index.js”):
[...] "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "webpack": "webpack" }, [...]
Il faut 2 terminaux:
yarnpkg run webpack webpack is watching the files… Hash: ed230c0c3f7b8e8a30d0 Version: webpack 4.43.0 Time: 1795ms Built at: 10/05/2020 18:24:17 Asset Size Chunks Chunk Names app.bundle.js 998 bytes 0 [emitted] app app.bundle.js.map 4.62 KiB 0 [emitted] [dev] app Entrypoint app = app.bundle.js app.bundle.js.map [0] ./src/index.js 43 bytes {0} [built]
J'utilise cette 2ème méthode car je préfère concentrer les modifications dans le fichier webpack.config.js.
Webpack a créé le dossier dist avec les fichier app.bundle.js et app.bundle.js.map dedans.
python manage.py runserver
Visu du résultat:
Git:
git add -A git commit -m "build(webpack): yarnpkg run webpack make js bundle for django."
yarnpkg add react react-dom info Direct dependencies ├─ react-dom@16.13.1 └─ react@16.13.1
Mise à jour de webpack.config.js:
const path = require('path') module.exports = { entry: { app: './src/index.js' }, watch: true, devtool: 'source-map', output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', options: { presets: ['@babel/react'] } } ], } ] }, resolve: { extensions: [ '.js' ] } }
Modifions le fichier src/index.js (suppression du test alert):
import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( <div> <h1>This is JSX !!</h1> </div>, document.getElementById("root") )
Modifions le fichier index.html pour accueilir le JSX:
{% load static %} <html> <head> <title>Demo</title> <link rel="stylesheet" href="{% static 'css/main.css' %}"/> </head> <body> <div id="root"></div> <script src="{% static 'dist/app.bundle.js' %}"></script> </body> </html>
Visu:
Git:
git add -A git commit -m "build(react): yarnpkg run webpack make react js bundle for jango."
Mise à jour de webpack.config.js
entry: { app: './src/js/index.js' },
Git:
git add -A git commit -m "build(webpack): Move src/index.js to src/js/index.js." git commit -m "build(webpack): Fix webpack.config.js with src/js/index.js"
2020-05-11
Les modules SASS ont été installés au début de cette procédure. Pour rappel :
yarnpkg add -D style-loader css-loader sass sass-loader node-sass
yarnpkg add -D mini-css-extract-plugin └─ mini-css-extract-plugin@0.9.0
Dans le fichier webpack.config.js ajouter la constante MiniCssExtractPlugin: et remplacer 'style-loader':
const path = require('path') const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { entry: { app: './src/js/index.js' }, mode: 'development', watch: true, devtool: 'source-map', output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', options: { presets: ['@babel/react'] } } ], }, { test: /\.(scss)$/, exclude: /node_modules/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader', ], } ] }, plugins: [ new MiniCssExtractPlugin({ filename: '../css/index.css', }) ], resolve: { extensions: [ '.js' ] } }
Créer le dossier src/scss avec index.scss dedans.
$h1-color: #3465A4; h1 { color: $h1-color; }
Dans le fichier index.js ajouter l'importation de index.scss:
import '../scss/index.scss'; import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( <div> <h1>This is JSX with SASS style file!!</h1> </div>, document.getElementById("root") )
Dans le fichier index.html mettre à jour l'appel du static/css/index.css
{% load static %} <html> <head> <title>Demo</title> <link rel="stylesheet" href="{% static 'css/index.css' %}"/> </head> <body> <div id="root"></div> <script src="{% static 'dist/app.bundle.js' %}"></script> </body> </html>
Visu:
Git:
git add -A git commit -m "build(webpack): Add SASS transpiler. Tested in Django with JSX and SASS." git commit -m "test(react): This is ReactJS JSX with SASS style file powered by Django!!"
2020-05-12
Dans le dossier static :
yarnpkg add foundation-sites
info Direct dependencies
└─ foundation-sites@6.6.3
Ajouter les @import et @include dans le fichier Sass:
@import 'foundation-sites/scss/foundation'; @include foundation-global-styles; @include foundation-typography; .content { margin-top: 10px; margin-left: 20px; } $h1-color: #3465A4; .title { color: $h1-color; } .mybutton { @include button(); margin-left: 50px; // exemple avec customisation des couleurs: // @include button(false, #3B3933, #2A2926, #EDEDED, "solid"); }
Détail du fichier JSX correspondant:
import '../scss/index.scss'; import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( <div className="content"> <h3 className="title"> This is ReactJS JSX with SASS file and Foundation Zurb style, </h3> <h2>powered by Django!!</h2> <a href="about.html" className="mybutton">Learn More</a> </div>, document.getElementById("root") )
Rendu:
git:
git add -A git commit -m "build(foundation): Add Foundation Zurb CSS framework. Test typo & button better presentation."
2020-05-15
Affin d'être conforme à la méthode donnée dans l'outil officiel creat-react-app voici la mise en place:
C'éer le fichier App.js :
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import '../scss/index.scss'; class App extends Component { render() { return ( <div className="content"> <h3 className="title"> This is ReactJS 'App.js & class App render' JSX with SASS file and Foundation Zurb style, </h3> <h2>powered by Django!!</h2> <a href="about.html" className="mybutton">Learn More</a> </div> ); } } export default App;
Mettre à jour index.js permettant l'appel du component App.js:
import React from 'react'; import ReactDOM from 'react-dom'; import '../scss/index.scss'; import App from './App'; ReactDOM.render(<App />, document.getElementById("root"));
La page HTML reste inchangée, voici le code pour rappel:
C'est transparent pour l'utilisateur, seul le texte est changer pour montrer que ça fonctionne:
Git:
git add -A git commit -m "build(reactJS): Use App.js with App render, main component."
J'utilise les librairies de Compass pour mettre en relief certains composant comme les cadres, boutons et ligne de tableau le survol d'éléments, en utilisant les dégradés.
yarnpkg add compass compass-mixins info Direct dependencies ├─ compass-mixins@0.12.10 └─ compass@0.1.1
Exemple d'utilisation:
// #### Foundation Zurg #### @import 'foundation-sites/scss/foundation'; @include foundation-global-styles; @include foundation-typography; // #### Compass framework lib #### @import "../../node_modules/compass-mixins/lib/compass/css3"; // colors definition: $body-color: #2F2F2F; $title-color: #f0f0f0; $power-color: #ff8000; body { background: $body-color; } .content { background: #3B3B3B; margin-top: 10px; margin-left: 20px; margin-right: 20px; padding: 10px; @include box-shadow( rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 2px 5px 2px); } .sub-content { background: #262626; padding: 10px; margin-bottom: 5px; border-color: #1E1E1E; border-radius: 4px; border-style: solid; border-width: 1px; @include box-shadow( rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.9) 0 1px 7px 1px inset); } .title { color: $title-color; } .django-power { color: $power-color; } .mybutton { // @include button(false, #3B3933, #2A2926, #EDEDED, "solid"); @include button(); margin-left: 50px; @include box-shadow($body-color 2px 2px 15px); @include box-shadow( rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.8) 0 1px 5px 1px inset); } ul { color: #C6C6C6; } code { font-family: menlo, monaco, "andale mono", "courier new", fixed; border-radius: 4px; background-color: #212121; @include box-shadow( rgba(255, 255, 255, 0.1) 0 1px 0, rgba(0, 0, 0, 0.9) 0 1px 7px 1px inset); color: #DADBB1; border-color: black; }
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import '../scss/index.scss'; class App extends Component { render() { return ( <div className="content"> <h3 className="title">Technical stuff inside this page:</h3> <div className="sub-content"> <ul> <li>Babel JSX bundler</li> <li>ReactJS 'App.js & class App render'</li> <li>SASS bundler file</li> <li>Foundation Zurb Framework style, ex: typo, button</li> <li>Compass SASS Framework, ex:<code>box-shadow</code> effects (frame & button)</li> </ul> </div> <h2 className="django-power">Django powered!</h2> <a href="about.html" className="mybutton">Learn More</a> </div> ); } } export default App;
Rendu:
Git:
git add -A git commit -m "build(compass): Add compass libraries & mixins." git add -A git commit -m "fix(render): Fix page typo." git add -A git commit -m "fix(render): Fix page typo again."
2020-05-17
Pour optimiser le traitement de collectstatic de Django, il est préférable de sortie webpack et surtout le dossier node_modules du dossier static.
Modifier la sortie de webpack.config.js: output: {…} est actualiser le chemin '../static/js':
const path = require('path') const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { entry: { app: './src/js/index.js' }, mode: 'development', watch: true, devtool: 'source-map', output: { filename: '[name].bundle.js', path: path.resolve(__dirname, '../static/js') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: [ { loader: 'babel-loader', options: { presets: ['@babel/react'] } } ], }, { test: /\.(scss)$/, exclude: /node_modules/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader', ], } ] }, plugins: [ new MiniCssExtractPlugin({ filename: '../css/index.css', }) ], resolve: { extensions: [ '.js' ] } }
tree -L 2 . ├── config_prj │ ├── asgi.py │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ ├── views.py │ └── wsgi.py ├── db.sqlite3 ├── frontend │ ├── dist_not_used │ ├── node_modules │ ├── package.json │ ├── src │ ├── webpack.config.js │ ├── yarn-error.log │ └── yarn.lock ├── manage.py ├── Pipfile ├── Pipfile.lock ├── reporting │ ├── admin.py │ ├── apps.py │ ├── __init__.py │ ├── migrations │ ├── models.py │ ├── tests.py │ └── views.py ├── static │ ├── css │ └── js └── templates └── index.html
Git:
git add -A git commit -m "build(frontend): New static structure without Webpack inside."
python manage.py runserver
yarnpkg run webpack