-Ajout de pip install
lorsque vous souhaitez ajouter un module pendant le développement
-J'avais une très mauvaise compréhension de la commande docker-compose run
, donc je l'ai corrigée et ai changé le style d'écriture pour utiliser la commande docker exec
comme alternative.
Maintenant que nous avons couvert les bases de Python, nous allons créer un environnement pour nous habituer à Django, et l'article du planificateur ne contient qu'un tutoriel sur les bases de Django. Ceci est la sortie lorsque vous faites cela.
Article qui permet le développement de système avec Django (Python) _Introduction
Créer un environnement django avec docker-compose (MariaDB + Nginx + uWSGI) Python3.6 + NGINX + MariaDB10 + uWSGI Django Environment Greedy Set avec Docker-Compose
Il a été construit dans l'environnement suivant en référence aux deux articles ci-dessus et à l'environnement.
・ Accueil Windows10 ・ Docker version 19.03.1 (spécification Docker Toolbox) ・ VirtualBox 6.0.16 ・ Python3.8 ・ Django 3 ・ Mariadb 10.1 ・ Nginx 1.13
.
├── db
│ ├── data
│ └── sql
│ └── init.sql
├── docker-compose.yml
├── nginx
│ ├── conf
│ │ └── app_nginx.conf
│ ├── log
│ └── uwsgi_params
├── python
│ ├── Dockerfile
│ └── requirements.txt
├── src
│ └── project
│ ├── app
│ │ └── __init__.py
│ │ └── settings.py
│ │ └── urls.py
│ │ └── uwsgi.log
│ │ └── views.py
│ │ └── wsgi.py
│ │
│──── ──├── migrations
│ │
│ ├── project
│ │ └── __init__.py
│ │ └── settings.py
│ │ └── urls.py
│ │ └── uwsgi.log
│ │ └── views.py
│ │ └── wsgi.py
│ │
│ └── manage.py
│ └── uwsgi.ini
└── static
Dockerfile
FROM python:3.8-alpine
ENV PYTHONUNBUFFERED 1
ENV PYTHONIOENCODEING utf-8
ENV APP_PATH code
# /$APP_C'est également possible avec PARH, mais cette fois, il est décrit car il s'agit d'éviter les bogues et de s'entraîner.
WORKDIR /code
# /le code est$APP_Également possible avec PATH
COPY ./requirements.txt /$APP_PATH
RUN apk add --no-cache --virtual .build-deps bash gcc musl-dev libffi-dev \
g++ libgcc libstdc++ libxml2-dev libxslt-dev openssl-dev curl \
&& apk add --no-cache --virtual --update-cache\
jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev \
mariadb-dev mariadb-connector-c-dev \
&& pip install cython && pip install -U pip && pip install -r requirements.txt
RUN rm -rf /var/cache/apk/* && \
rm -rf /tmp/*
Revoyons ici à nouveau. Quant à FROM et ENV, je retirerai la première apparition car c'est comme un sortilège. Tout d'abord, la notation alpine. C'est comme Alpine Linux, une version ultra-légère de Linux. Et comme Docker est comme un chef-d'œuvre de Linux, essayer de réduire le poids de l'image dans Docker en se basant sur cela revient à la notation -alpine ... pour le moment. .. Il existe également une notation -slim, et avec -alpine, il semble que certains paquets tels que Numpy peuvent avoir un problème lors de la construction avec Docker. C'est parce que le traitement de type C est intégré dans un tel package, mais l'image de la notation alpine est Pour le moment, comprenons simplement que la notation alpine dans Docker rend l'image plus claire.
Ensuite, WORKDIR et COPY, WORKDIR est la spécification du répertoire de travail dans l'environnement virtuel. Plus tard, je le définirai dans docker-compose.yml, mais cette fois, je partagerai le dossier src côté hôte et le dossier de code de l'environnement virtuel, c'est-à-dire que le dossier de projet de l'application sera développé dans ce .. COPY est une instruction pour copier les fichiers existants dans le chemin vers le dossier spécifié par $ APP_PATH dans l'environnement virtuel. Étant donné que le chemin d'accès côté hôte est spécifié en fonction du répertoire dans lequel se trouve le Dockerfile, c'est-à-dire que l'emplacement situé une étape vers le bas du dossier parent tel qu'il est vu depuis le Dockerfile est spécifié, il est donc décrit ci-dessus.
Après cela, installez divers packages avec RUN, principalement pour éviter les erreurs de traitement du système C qui se produisent en utilisant alpine (jusqu'à gcc ~ libxslt-dev) et des connecteurs pour la connexion à MariaDB. Enfin, mettez cython (Python accéléré utilisant le savoir-faire du langage C) avec pip, mettez à niveau pip et installez le package décrit dans requirements.txt.
requirements.txt
Django==3.0
django-bootstrap4
flake8==3.7.9
ipython==7.10.1
mysqlclient==1.4.6
Pillow==6.2.1
uwSGI==2.0.18
dj-static
whitenoise
Je l'ai inclus comme essai, Django, django-bootstrap4 et mysqlclient suffisent pour l'utiliser au niveau où vous commencez à étudier comme moi. Puisque uwSGI est implémenté en tant que source de référence, je vais l'essayer car c'est un gros problème.
Un module pour écrire simplement un formulaire d'inscription / correction Bootstrap en Python. Pour expliquer l'utilisation détaillée, il est nécessaire de comprendre un peu plus le mécanisme de View dans Django, alors passons à autre chose en sachant que si vous utilisez bootstrap 4 avec Django, vous devez l'inclure.
mysqlclient
Modules nécessaires pour se connecter à MySQL avec Python
En termes simples, il s'agit d'un serveur AP, c'est-à-dire d'un serveur d'applications. Jusqu'à présent, j'ai appris avec une compréhension duveteuse que je dois me préparer pour le serveur Web et le serveur d'applications pour le moment. Cette fois, j'ai eu l'occasion d'entrer dans la technologie appelée uWSGI, alors j'ai essayé de creuser un peu plus en me basant sur l'article de référence suivant.
Différences entre serveur Web et serveur d'applications dans le développement de Rails (traduction) Introduction à uWSGI À propos de «uWSGI» et du serveur d'applications J'expliquerai la différence entre le serveur Web et le serveur d'applications d'une manière facile à comprendre Quel est le rôle du serveur AP? Comprenons la différence avec le serveur Web
Quand je l'ai mis ensemble
・ Qu'est-ce que WSGI?
→ Abréviation de "Web Server Gateway Interface", qui est une règle de communication entre une application web Python et un serveur web ... En d'autres termes, un protocole. Bien sûr, la communication n'est pas possible sans protocole, mais apparemment le problème est que le support et le non-support du framework pour les serveurs Web sont mélangés. En Python, créer un protocole commun de cette manière permet de faire fonctionner n'importe quel framework prenant en charge WSGI, ce qui semble être l'arrière-plan de l'introduction de WSGI.
・ Alors qu'est-ce que uWSGI?
→ C'est une sorte de serveur d'application qui prend en charge WSGI. Vous pouvez utiliser la communication HTTP et les méthodes de communication de socket de domaine UNIX, mais je vais laisser cela car cela ne peut pas être aidé si je creuse plus profondément maintenant.
・ Qu'est-ce qu'un serveur Web et un serveur d'applications en premier lieu?
→ Le serveur Web est destiné à effectuer certains traitements après avoir reçu une demande de l'utilisateur. En d'autres termes, à moins que vous ne vous trouviez dans un environnement local, l'image est que la requête envoyée va d'abord au serveur Web et décide quoi en faire. Sauf pour les demandes dynamiques (demandes de CSS, Javascript, images, vidéos, etc. qui peuvent changer fréquemment), le traitement peut être effectué ici. A l'inverse, lorsque ces requêtes arrivent, on peut dire qu'elle a pour rôle de transmettre les requêtes au serveur d'application. Bien sûr, en CSS et en images, si elles sont statiques, vous pouvez les traiter ici.
Alors qu'est-ce qu'un serveur d'application? En bref, c'est celui qui exécute l'application. Les demandes et les réponses sont transmises là où elles sont faciles à comprendre. Prenant le processus de connexion comme exemple
Il se trouve que. J'ai senti que même une seule connexion était en fait un processus assez compliqué.
docker-compose.yml
version: '3.7'
volumes:
django.db.volume:
name: django.db.volume
services:
nginx:
image: nginx:1.13
container_name: app_nginx
ports:
- "8000:8000"
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
- ./static:/static
- ./nginx/log:/var/log/nginx
depends_on:
- python
db:
tty: true
image: mariadb:10.1
container_name: app_mariadb
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
TZ: 'Asia/Tokyo'
volumes:
- django.db.volume:/var/lib/mariadb
- ./db/sql:/docker-entrypoint-initdb.d
python:
build: ./python
image: python_blog
container_name: app_python
command: uwsgi --ini /code/project/uwsgi.ini
environment:
- DATABASE_HOST=db
volumes:
- ./src:/code
- ./static:/static
- ./python:/code/python
expose:
- "8888"
depends_on:
- db
Pour récapituler, la spécification de chemin dans les volumes est «côté hôte: côté environnement virtuel» et «tty: true» est une description qui maintient le conteneur en place. Cette fois, j'étais accro au marais parce que je travaillais avec Docker sur Windows, ou en raison de la commodité du système de conteneur Docker, il y avait beaucoup de difficulté à éliminer l'erreur de connexion à la base de données. À la suite de l'enquête, les deux ont été soulevés comme raison, mais je pense que la raison de cette dernière est que j'ai reflété les changements et mis fin à Docker avec duvet. Quoi qu'il en soit, cette fois, le volume de la base de données doit être conservé dans Docker en préparant un répertoire pour stocker les informations de la base de données du côté hôte et en le partageant. Tout d'abord, je l'ai résolu en ne le faisant que pour la persistance du conteneur mariadb afin de monter le volume au début. Au fait, django.db.volume n'existe pas dans le répertoire du côté Windows? Cependant, dans le cas de Docker Toolbox, c'est très compliqué, c'est-à-dire
Windows ⇒ Virtual Box ⇒ Docker == Hôte principal ⇒ Hôte vu depuis Docker (invité vu depuis Windows) ⇒ Invité
Le volume créé cette fois-ci étant dans la boîte virtuelle, il ne sera pas affiché sous Windows, ce qui est déroutant. Quoi qu'il en soit, l'un des avantages de Docker est que vous pouvez facilement créer et supprimer des conteneurs, mais si des données telles que DB ne sont pas persistantes, cela provoquera une erreur de connexion, alors assurez-vous d'en faire un moyen de persistance. Prenons-le. À propos, si vous utilisez dokcer-compose.yml, vous devriez probablement apporter diverses modifications et mises à jour en jouant avec cela au lieu du Dockerfile, mais dans ce cas, rappelez-vous que la construction peut être reflétée sans en avoir besoin. C'était. Dans le cas de Dockerfile, la construction est requise, donc si vous ne rendez pas DB persistant, vous obtiendrez probablement une erreur (rencontrée)
Pour nginx, écrivez les paramètres dans le fichier de configuration et préparez un fichier de paramètres pour uWSGI.
app_nginx.conf
upstream django {
ip_hash;
server python:8888;
}
# configuration of the server(Configuration du serveur)
server {
# the port your site will be served on
listen 8000;
# the domain name it will serve for
server_name 127.0.0.1; # substitute your machine`s IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M;
location /static {
alias /static;
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
}
}
L'accès est d'abord reçu au port 8000. Ensuite, s'il s'agit d'une requête à un fichier statique, transmettez-la à static de nginx. Si vous devez transmettre la demande à un autre serveur d'applications (uWSGI), ignorez la demande sur le port 8888. N'oubliez pas de spécifier le répertoire où se trouve le fichier de paramètres uWSGI à la fin.
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
C'est un soi-disant sortilège.
Si vous souhaitez installer des packages supplémentaires pendant le développement, vous pouvez aller directement dans le conteneur et faire python -m pip install
, mais comme j'ai créé requirements.txt
, je vais utiliser ceci Je veux.
Cependant, si rien n'est fait, une erreur se produira même si vous dites python -m pip install requirements.txt
.
Avez-vous fait COPY
et ʻADD` dans DockerFile? J'avais une question, alors j'ai décidé de la vérifier pour le moment.
# docker exec -it app_trouver de python bash./Résultat de l'exécution de la commande
./
./project
./project/app
./project/app/admin.py
./project/app/apps.py
./project/app/migrations
./project/app/migrations/0001_initial.py
./project/app/migrations/0002_sampledb.py
./project/app/migrations/__init__.py
./project/app/migrations/__pycache__
./project/app/migrations/__pycache__/0001_initial.cpython-38.pyc
./project/app/migrations/__pycache__/0002_sampledb.cpython-38.pyc
./project/app/migrations/__pycache__/__init__.cpython-38.pyc
./project/app/models.py
./project/app/tests.py
./project/app/urls.py
./project/app/views.py
./project/app/__init__.py
./project/app/__pycache__
./project/app/__pycache__/admin.cpython-38.pyc
./project/app/__pycache__/apps.cpython-38.pyc
./project/app/__pycache__/models.cpython-38.pyc
./project/app/__pycache__/urls.cpython-38.pyc
./project/app/__pycache__/views.cpython-38.pyc
./project/app/__pycache__/__init__.cpython-38.pyc
./project/manage.py
./project/media
./project/polls
./project/polls/admin.py
./project/polls/apps.py
./project/polls/migrations
./project/polls/migrations/0001_initial.py
./project/polls/migrations/0002_auto_20200408_1848.py
./project/polls/migrations/__init__.py
./project/polls/migrations/__pycache__
./project/polls/migrations/__pycache__/0001_initial.cpython-38.pyc
./project/polls/migrations/__pycache__/0002_auto_20200408_1848.cpython-38.pyc
./project/polls/migrations/__pycache__/__init__.cpython-38.pyc
./project/polls/models.py
./project/polls/tests.py
./project/polls/urls.py
./project/polls/views.py
./project/polls/__init__.py
./project/polls/__pycache__
./project/polls/__pycache__/admin.cpython-38.pyc
./project/polls/__pycache__/apps.cpython-38.pyc
./project/polls/__pycache__/models.cpython-38.pyc
./project/polls/__pycache__/tests.cpython-38.pyc
./project/polls/__pycache__/urls.cpython-38.pyc
./project/polls/__pycache__/views.cpython-38.pyc
./project/polls/__pycache__/__init__.cpython-38.pyc
./project/project
./project/project/settings.py
./project/project/urls.py
./project/project/uwsgi.log
./project/project/views.py
./project/project/wsgi.py
./project/project/__init__.py
./project/project/__pycache__
./project/project/__pycache__/settings.cpython-38.pyc
./project/project/__pycache__/urls.cpython-38.pyc
./project/project/__pycache__/views.cpython-38.pyc
./project/project/__pycache__/wsgi.cpython-38.pyc
./project/project/__pycache__/__init__.cpython-38.pyc
./project/templates
./project/templates/admin
./project/templates/admin/base_site.html
./project/templates/admin/index.html
./project/templates/app_folder
./project/templates/app_folder/page01.html
./project/templates/app_folder/page02.html
./project/templates/app_folder/top_page.html
./project/templates/base.html
./project/templates/polls
./project/templates/polls/detail.html
./project/templates/polls/index.html
./project/templates/polls/results.html
./project/uwsgi.ini
La commande find. /
Est une commande Linux, ce qui signifie rechercher et afficher les répertoires sous le dossier racine
.
Certains fichiers pour les tutoriels Django après cet article sont également mélangés, mais si vous vérifiez attentivement, vous pouvez voir que requirements.txt
est manquant.
Dans DockerFile, COPY ./requirements.txt / code
est utilisé, et même s'il s'agit d'un conteneur créé à partir de cette image, je ne comprends pas pourquoi.
Cependant, une chose que j'ai à l'esprit est que ma compréhension de la commande docker-compose run
était trop diversifiée et trop diversifiée, ce qui aboutissait à un nombre infini de conteneurs ...
Si quelqu'un sait, faites-le moi savoir.
Maintenant, la solution pour le moment est de monter requirements.txt
sur le conteneur.
J'ai donc ajouté la description de ./python: / code / python
à docker-compose.yml
.
Après cela, vous pouvez faire ʻup et entrer avec la commande
docker exec, puis vous pouvez faire
pip install -r. / Python / requirements.txt`, ainsi vous pouvez prendre en charge l'installation de paquets supplémentaires.
Lorsque vous êtes prêt, essayez de créer un conteneur avec docker-compose up -d --build
.
Pour récapituler, l'option -d permet au conteneur de fonctionner en arrière-plan.
…… C'est normal de le faire, mais si vous le démarrez tel quel, il ne démarrera pas vraiment bien.
La raison en est que uWSGI n'est pas encore prêt.
Si vous regardez à nouveau docker-comopose.yml
, vous pouvez voir que les conteneurs nginx et python ont une spécification dependency_on.
Nous avons déjà appris qu'il s'agit d'une indication des dépendances de conteneurs.
En d'autres termes, les conteneurs nginx et python ne peuvent pas être démarrés à moins que le conteneur db ne soit démarré.
Cependant, le serveur db essentiel ne fonctionne pas sans le serveur d'applications, donc uWSGI n'est pas prêt maintenant et le conteneur ne démarre pas ... C'est ce qui se passe.
Alors, créez d'abord un projet Django et créez un fichier de configuration uwsgi.
docker-compose run --rm python django-admin.py startproject project
La commande run ** crée un nouveau conteneur ** et exécute la commande spécifiée.
Donc ** Si vous l'utilisez beaucoup, vous aurez un nombre infini de conteneurs **.
Veillez donc à utiliser la commande --rm
sauf si vous avez une intention spécifique.
À propos, il existe également une commande appelée docker-compose exec $ {service_name} $ {command}
qui exécute la commande dans le conteneur en cours d'exécution.
Par exemple, si vous faites docker-compose exec python bash
, vous pouvez entrer le conteneur du service python et y exécuter la commande bash.
Maintenant, après l'exécution, spécifiez le nom du service que vous avez défini et le sort qui générera le projet Django.
Ensuite, un dossier avec le nom spécifié après start project
sera créé dans la zone spécifiée par WORKDIR.
Et enfin, le conteneur est supprimé avec la commande --rm
.
Cependant, comme le résultat de django-admin.py startproject project
reste du côté hôte, il peut être reflété dans le lancement ultérieur du conteneur, il n'y a donc pas de problème.
uwsgi.ini
[uwsgi]
socket = :8888
module = project.wsgi
wsgi-file = /code/project/project/wsgi.py
logto = /code/project/project/uwsgi.log
chdir=/code/project
py-autoreload = 1
Après cela, créez un fichier de paramètres comme décrit ci-dessus et placez-le dans le même répertoire que manage.py
du fichier de projet créé.
Ce qui est écrit est le port utilisé par uWSGI, le fichier journal et l'emplacement du fichier wsgi.
En passant, gardez à l'esprit que les projets Django spécifient toujours des répertoires et exécutent des commandes basées sur manage.py
.
Quand tu as fini si loin
$ docker-compose up -d
$ docker ps -a
Lancez le sort. Le dernier sort peut afficher une liste de conteneurs, alors assurez-vous que 3 conteneurs sont en place et tous sont en place. Comme je l'ai mentionné au début, lors de l'utilisation de MySQL avec docker, il arrive parfois qu'il ne devienne pas ici mais qu'il devienne immédiatement exit. Cette fois, je pense qu'il n'y a pas de problème car j'ai pris des mesures qui peuvent être faites jusqu'à présent, mais personnellement j'ai pensé qu'il valait mieux préparer le tableau suivant avant de lancer le sort ici. ..
sql:./db/sql/init.sql
CREATE DATABASE IF NOT EXISTS Nom de base de données arbitraire CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS 'Tout nom d'utilisateur'@'%' IDENTIFIED BY 'password';
Le nom de la base de données spécifié sur GRANT ALL PRIVILEGES ON.* TO 'Nom de la base de données spécifié ci-dessus'@'%';
FLUSH PRIVILEGES; #n'oubliera pas
C'est un sort avec le style SQL familier.
MySQL crée toujours une base de données et un utilisateur, et si vous ne donnez pas d'abord à l'utilisateur créé tous les droits sur cette base de données (cela peut également être donné en unités de table), vous serez de mauvaise humeur, alors définissez ceci en premier Je le ferai.
En passant, le nom d'utilisateur et le mot de passe sur la deuxième ligne peuvent également être définis dans docker-compose.yml
.
Cette fois, le mot de passe root de MySQL est défini dans la partie MYSQL_ROOT_PASSWORD: root
.
Cette fois, nous donnerons tous les droits à toutes les bases de données, alors définissez l'utilisateur root.
Au fait, le nom d'utilisateur et le mot de passe sont définis en tant que root, mais bien sûr, cela est autorisé car il est local, et dans l'environnement de production, c'est trop désagréable pour la sécurité, alors définissons-le correctement.
Comme vous pouvez le voir en écrivant jusqu'à présent, le fait est qu'il s'agit d'un fichier d'initialisation SQL.
Maintenant que vous en êtes arrivé là, jetons un œil au fichier de configuration de Django.
project/project/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_test',
'USER': 'root',
'PASSWORD': 'root',
'HOST': 'db',
'PORT': '3306',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
'charset': 'utf8mb4',
},
}
}
#Omission
STATIC_ROOT = '/static'
STATIC_URL = '/static/'
Vous pouvez presque comprendre ce qui est écrit.
Il semble que la partie ENGINE puisse être différente selon la version de Django, mais dans ce cas, veuillez la réécrire dans une version appropriée.
Après cela, définissez le nom de la base de données et les éléments liés à l'utilisateur root.
Pour la partie HOST, définissez le nom de service du conteneur qui contient la base de données spécifiée dans docker-compose.yml
, et pour PORT, définissez également le port spécifié ici.
OPTION est un sort.
'init_command':" SET sql_mode = 'STRICT_TRANS_TABLES' "
Il est recommandé de le spécifier ici, alors définissons-le.
Cela semble être un mode qui résout de nombreux problèmes d'intégrité des données dans MySQL.
Au fait, j'ai eu une erreur si je ne l'ai pas défini.
La dernière partie est le paramètre de répertoire de fichier statique, sinon le fichier statique ne sera pas chargé.
Quand tu as fini si loin
Entrez dans le conteneur avec docker exec -it app_python bash
cd ./project/
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
Jetons le sort. Si la migration est terminée avec succès sans générer d'erreur ici, cela signifie que l'accès à la base de données a réussi, alors créons un conteneur avec up -d plus tôt.
Après cela, nous installerons Django. Avant cela, créez d'abord un dossier d'application dans le projet
Entrez dans le conteneur avec docker exec -it app_python bash
cd ./project/
python manage.nom du dossier py startapp
Après l'exécution, définissez settings.py
comme suit.
project/project/settings.py
"""
Django settings for project project.
Generated by 'django-admin startproject' using Django 2.1.5.
For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '&$l0ho%f&-w%&t_2l=@98u(i_58t15d-jn+ln5fuyvy(^l88^t'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app.apps.AppConfig', #ajouter à
'bootstrap4' #ajouter à
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', #ajouter à
]
ROOT_URLCONF = 'project.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], #Spécifiez le répertoire du dossier contenant le modèle html
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'builtins':[
'bootstrap4.templatetags.bootstrap4',#Ajoutez ici!
],
},
},
]
WSGI_APPLICATION = 'project.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_test',
'USER': 'root',
'PASSWORD': 'root',
'HOST': 'db',
'PORT': '3306',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
'charset': 'utf8mb4',
},
}
}
# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = '/static'
# Custom User
AUTH_USER_MODEL = 'app.User'
#Paramètres liés aux fichiers multimédias
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
Lors de l'extrait
'app.apps.AppConfig', #ajouter à
'bootstrap4' #ajouter à
apps.py
from django.apps import AppConfig
class AppConfig(AppConfig):
name = 'app'
Cette partie spécifie l'emplacement de ʻapps.py ci-dessus. Comme vous pouvez le voir, ʻapps.py
importe l'objet ʻAppConfig du module
django.apps. N'oubliez pas de définir
name = 'nom du dossier d'application'` où vous avez créé la classe ci-dessous.
Au fait, si vous n'ajoutez pas `` app.apps.AppConfig '' après avoir créé un dossier d'application, vous obtiendrez une erreur (histoire d'expérience).
La partie inférieure est le paramètre pour utiliser le bootstrap avec Django, alors ajoutez-le également.
'builtins':[
'bootstrap4.templatetags.bootstrap4',#Ajoutez ici!
],
C'est aussi une spécification pour l'utilisation du bootstrap, alors n'oubliez pas de l'ajouter.
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
Spécifiez le fuseau horaire et la langue de réglage de Djnago.
# Custom User
AUTH_USER_MODEL = 'app.User'
Il s'agit d'un paramètre pour l'utilisateur personnalisé à créer ultérieurement.
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
Il devient le paramètre d'accès du fichier multimédia. Il est utilisé lors de la mise en œuvre de la fonction de téléchargement et de la fonction d'affichage du fichier téléchargé en tant que contenu sur l'écran de l'application. Ceci termine les préparatifs de base pour l'utilisation de Django.
À partir de là, nous allons créer un modèle. Puisque Django est un framework, il est composé de modèles MVC comme Laravel. C'est ce qu'on appelle le modèle MVT dans Django.
En d'autres termes, il s'agit d'un modèle `Model / Tenmplaete / View '. En tant que rôle
Modèle: contrôle de base de données Modèle: contrôlez l'écran. Le rôle de View dans le modèle MVC Vue: le rôle du contrôle global. Rôle du contrôleur dans le modèle MVC
Ce sera. Notez que la vue dans le modèle MVC et la vue dans le modèle MTV ont des rôles différents. Par conséquent, le modèle peut être utilisé dans Django, nous allons donc le définir.
template/base.html
<!DOCTYPE html>
{% load bootstrap4 %}
{% bootstrap_css %}
{% bootstrap_javascript jquery='slim' %}
{% load static %}
<html lang="ja">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type='text/css' href="{% static 'css/style.css' %}">
<link rel="stylesheet" href="https://cccabinet.jpn.org/bootstrap4/css/style.css">
<title>Exemple de développement Django</title>
{% block extra_css %}{% endblock %}
</head>
<body>
<!-- navbar -->
<div class="container">
<div class="row">
<div class="col-12">
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bs-navbar" style="background-color:cadetblue;" id='bs-navbar'>
<a class="navbar-brand mr-md-2" href="/app/top_page">
Exemple d'écran de développement
</a>
<!-- layout_dammy -->
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class='nav-link' href="#"></a></li>
<li class="nav-item"><a class='nav-link' href="#"></a></li>
</ul>
<!-- layout -->
<ul class="navbar-nav">
<li class="nav-item"><a class="nav-link" href="/#">Échantillon 1</a></li>
<li class="nav-item"><a class="nav-link" href="/#">Échantillon 2</a></li>
<li class="nav-item"><a class="nav-link" href="/#">Échantillon 3</a></li>
<li class="nav-item"><a class="nav-link" href="/accounts/login">S'identifier</a></li>
<li class="nav-item"><a class="nav-link" href="/accounts/logout">Se déconnecter</a></li>
</ul>
</nav>
</div><!-- /.col-12 -->
</div><!-- /.row -->
</div>
<!-- sidebar&main-contents -->
<div class="container-fluid" id="content">
<div class="row flex-xl-nowrap">
<!-- sidebar -->
<div id="sidemenu" class="col-2 d-none d-md-block bg-light sidebar align-self-start">
<div class="sidebar-sticky">
<ul class='nav flex-column'>
<li class="nav-item">
<nav class="navbar navbar-light bg-light">
<a class="navbar-brand" href="/#">
<span data-feather=""></span>TOP page
</a>
</nav>
</li>
<li class="nav-item">
<nav class="navbar navbar-light bg-light">
<a class="navbar-brand" href="/#">
<span data-feather=""></span>Barre latérale 1
</a>
</nav>
</li>
<li class="nav-item">
<nav class="navbar navbar-light bg-light">
<a class="navbar-brand" href="/#">
<span data-feather=""></span>Barre latérale 2
</a>
</nav>
</li>
<li class="nav-item">
<nav class="navbar navbar-light bg-light">
<a class="navbar-brand" href="/#">
<span data-feather=""></span>Barre latérale 3
</a>
</nav>
</li>
<li class="nav-item">
<nav class="navbar navbar-light bg-light">
<a class="navbar-brand" href="/#">
<span data-feather=""></span>Barre latérale 4
</a>
</nav>
</li>
<li class="nav-item">
<nav class="navbar navbar-light bg-light">
<a class="navbar-brand" href="/#">
<span data-feather=""></span>Barre latérale 5
</a>
</nav>
</li>
</ul>
</div><!-- /.sidebar-sticky -->
</div><!-- /#sidemenu -->
<div class="col-10">
{% block contents %}
{% endblock %}
</div><!-- /.col-10 -->
</div><!-- /.row -->
</div><!-- /#content -->
</body>
</html>
<!-- sidebar-icon -->
<!-- use-icon: https://voyager-jp.com/blog/javascript/feather/ -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/feather-icons/4.9.0/feather.min.js"></script>
<script>feather.replace()</script>
Tout d'abord, créez un modèle pour la partie commune à chaque page. C'est un en-tête ou une barre de navigation. Les notations comme «{%%}» sont des sorts utilisés dans les modèles. Voici quelques extraits
{% load bootstrap4 %}
{% bootstrap_css %}
{% bootstrap_javascript jquery='slim' %}
{% load static %}
Charge le module d'amorçage, jQuery et les fichiers statiques. Si vous ne le spécifiez pas, le bootstrap ne sera pas appliqué, alors n'oubliez pas. S'il y a un sort comme une commande comme celle-ci
<link rel="stylesheet" type='text/css' href="{% static 'css/style.css'%}">
Vous pouvez également l'utiliser pour simplifier la spécification du chemin. Au fait
{% block %}
{% endblock %}
Telle est la désignation de la zone. Par exemple
{% block extra_css %}{% endblock %}
Cela signifie que block
en ʻendblock sera changé en
block nommé ʻextra_css
.
Le bloc
spécifié de cette manière devient la valeur par défaut, et lorsqu'il est hérité par le modèle enfant ci-dessous
La zone si le nom du block
n'est pas spécifié, comme {% block%} ~ {% endblock%}
, ou si` {% block extra_css%} {% endblock%} ʻest spécifié. Sera inséré.
Donc
{% block contents %}
{% endblock %}
Si vous lancez un sort comme celui ci-dessus, vous pouvez voir que la partie du modèle enfant qui lance le même sort est insérée.
Au fait, cette fois, je charge Bootstrap avec CDN, mais il y a divers problèmes avec CDN, donc si possible, je voudrais télécharger le package et charger celui que j'ai mis localement.
Après cela, je vais créer un modèle enfant
templates/app_folder/top_page.html
{% extends 'base.html' %}
{% block contents %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center mt-5 border-bottom">
<h1 class="h2">haut de page</h1>
</div>
<div>
<h4>Décrivez le contenu ici</h4>
</div>
{% endblock %}
templates/app_folder/page01.html
{% extends 'base.html' %}
{% block contents %}
<h4 class="mt-5 mb-4 border-bottom">Entrez les conditions de recherche</h4>
<form action="{% url 'app:top_page' %}" method="post">
<div class="container-fluid">
<div class="row">
<div class="col-2">
<input class="form-control" type="next" name="input_data" maxlength="255">
</div><!-- /.col-2 -->
<div class="col-2">
<div class="text-left align-bottom">
<button type="submit" name="button" class="btn btn-info">
Chercher
</button>
</div><!-- /.text-left -->
</div><!-- /.col-2 -->
</div><!-- /.row -->
</div><!-- /.container-fluid -->
{% csrf_token %}
</form>
{% endblock %}
templates/app_folder/page02.html
{% extends 'base.html' %}
{% block contents %}
<h4 class="mt-5 mb-4 border-bottom">Afficher les résultats de la recherche DB</h4>
<div class="container-fluid">
<div class="row">
<div class="col-4">
<p>sample1:{{result_sample1}}</p>
<p>sample2:{{result_sample2}}</p>
</div>
</div>
</div>
{% endblock %}
Le sort de {% extend'base.html '%}
hérite du modèle parent précédent.
Le contenu de la page01 et de la page02
・ Recevez les conditions de recherche du formulaire de saisie à l'écran -Obtenir des données de la base de données en fonction des conditions de recherche ・ Passez les données acquises au modèle (écran)
Cela signifie que vous avez créé une interface utilisateur pour effectuer le processus sur l'écran de gestion.
Maintenant que le modèle est terminé, définissez également la vue et le modèle.
Pour citer l'article du planificateur répertorié dans l'article de référence
app_config / views.py: contrôle approximatif de l'ensemble app_folder / views.py: contrôler les fonctionnalités individuelles
Notez que le même views.py
que, mais avec des rôles différents, ce qui est déroutant.
Au fait, cette fois
ʻApp_config / views.py est
project / project / views.py (situé dans le même répertoire que settings.py). Remplacez ʻapp_folder / views.py
par project / app / views.py
.
project/project/views.py
from django.shortcuts import render, redirect, reverse
from django.views import View
class index(View):
def get(self, request, *args, **kwargs):
return redirect(reverse('app:top_page'))
index = index.as_view()
Si le système est accédé, il sera passé à la page supérieure.
project/app/views.py
from django.shortcuts import render
from django.views import View
from .models import SampleDB
class SampleView(View):
def get(self, request, *args, **kwargs):
return render(request, 'app_folder/page01.html')
def post(self, request, *args, **kwargs):
input_data = request.POST['input_data']
result = SampleDB.objects.filter(sample1=input_data)
result_sample1 = result[0].sample1
result_sample2 = result[0].sample2
context={'result_sample1':result_sample1, 'result_sample2':result_sample2}
return render(request, 'app_folder/page02.html', context=context,)
top_page = SampleView.as_view()
Faites attention aux fautes de frappe.
Ne vous trompez pas, car depuis et importer au début sont des sorts. La dernière partie consiste à importer les objets de table à partir du modèle.
def get(self, request, *args, **kwargs):
return render(request, 'app_folder/page01.html')
La méthode render est une méthode qui renvoie un objet HttpResponse. En définissant une requête dans l'argument et en spécifiant le chemin de l'écran où vous souhaitez renvoyer le résultat dans le deuxième argument, le résultat comprenant les informations autour de la session y sera retourné.
def post(self, request, *args, **kwargs):
input_data = request.POST['input_data']
result = SampleDB.objects.filter(sample1=input_data)
result_sample1 = result[0].sample1
result_sample2 = result[0].sample2
context={'result_sample1':result_sample1, 'result_sample2':result_sample2}
return render(request, 'app_folder/page02.html', context=context,)
Il s'agit d'une méthode pour recevoir des requêtes POSTées à partir du formulaire d'entrée. Dans la variable de contexte, le processus consiste à mapper du "nom de la variable" passé au modèle à la "valeur de la variable" et de le transmettre à la variable avec la méthode de rendu. Il sera renvoyé dans ʻapp_folder / page02.html`.
C'est juste, alors définissons le modèle ici également.
project/app/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
pass
class SampleDB(models.Model):
class Meta:
db_table = 'sample_table' # tablename
verbose_name_plural = 'sample_table' # Admintablename
sample1 = models.IntegerField('sample1', null=True, blank=True) #Variables et paramètres pour stocker les numéros
sample2 = models.CharField('sample2', max_length=255, null=True, blank=True) #Variables et paramètres pour stocker des chaînes de caractères
Chaque classe est chaque table.
En d'autres termes, si vous écrivez comme ceci, la table User et SampleDB seront créés.
Puisque la table utilisée dans le modèle créé cette fois-ci est SampleDB, créez une classe, définissez models.Model
comme argument et écrivez les paramètres de la table sous la classe Meta.
db_table = 'sample_table' # tablename
verbose_name_plural = 'sample_table' # Admintablename
Cette partie est le paramétrage du nom de la table et du nom de la table affichés sur l'écran de gestion.
sample1 = models.IntegerField('sample1', null=True, blank=True) #Variables et paramètres pour stocker les numéros
sample2 = models.CharField('sample2', max_length=255, null=True, blank=True) #Variables et paramètres pour stocker des chaînes de caractères
En écrivant ainsi, vous définissez les données dans le tableau. En d'autres termes, cette table stockera les données d'ID et de chaîne.
Définissez l'URL requise pour accéder au système à partir de l'écran Web. S'agit-il d'un paramètre de routage dans Laravel?
Tout comme views.py
app_config / urls.py: conception d'URL à l'échelle du système app_folder / urls.py: conception d'URL dans des applications individuelles
Veuillez noter qu'il a le même nom de fichier et a un rôle différent. Au fait, cette fois
ʻApp_config / views.py est
project / project / urls.py (situé dans le même répertoire que settings.py). Remplacez ʻapp_folder / views.py
par project / app / urls.py
.
project/app/urls.py
from django.urls import path
from . import views
# URL_setting
app_name = 'app'
urlpatterns = [
path('top_page/', views.top_page, name='top_page')
]
Écrivez le chemin de chaque page dans la partie de ʻurl patterns`. Cette fois, seule la page TOP est créée (page01 et page02 sont exclues car ce sont des modèles d'écran de gestion), il n'y en a donc qu'un.
project/project/urls.py
"""project URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.1/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, include
from django.conf import settings
from django.conf.urls.static import static
from . import views
urlpatterns = [
#URL pour accéder au site de gestion
path('admin/', admin.site.urls),
#URL pour accéder à l'application "app" créée cette fois
path('app/', include('app.urls')),
#Si vous ne spécifiez aucune URL (app_config/views.Avec py, "app" automatiquement_(Déjà configuré pour accéder au "dossier")
path('', views.index, name='index'),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Enfin, créez un écran de gestion.
Parce que vous devez créer un utilisateur administrateur pour cela
Entrez dans le conteneur avec docker exec -it app_python bash
cd ./project/
python manage.py createsuperuser
Lancez le sort. Sur quoi définissez-vous votre nom d'utilisateur, votre adresse e-mail et votre mot de passe lorsque vous êtes bloqué? On vous le demandera, veuillez donc le définir de manière arbitraire. Vient ensuite le paramétrage du site de gestion.
project/app/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
from.models import SampleDB
admin.site.register(User, UserAdmin)
admin.site.register(SampleDB)
Le site de gestion est
Normalement, vous devez apprendre MySQL etc. pour faire fonctionner DB Même si Python (Django) est complet, MySQL est impossible. .. Exploitons la base de données à l'écran depuis le site de gestion!
Alors, définissez-le comme ci-dessus en fonction du tableau à utiliser.
Maintenant, démarrons le système.
Avant cela, migrez la table et appliquez css sur le site de gestion.
J'ai fait la migration une fois il y a longtemps, mais depuis que j'ai défini une nouvelle table SampleDB, je vais le refaire.
C'est le sortilège.
Entrez dans le conteneur avec docker exec -it app_python bash
cd ./project/
python manage.py migrate
Vient ensuite l'application du CSS. Cela serait fait lors de l'utilisation de uWSGI. Les sorts sont les suivants
python manage.py collectstatic
Enfin quand c'est fait en toute sécurité
python manage.py runserver
C'est le démarrage du système.
Si aucune erreur n'est générée, le démarrage est terminé avec succès. Je vous remercie pour votre travail acharné.
Si cela ne fonctionne pas, essayez à nouveau docker-compose up -d
ou consultez le message d'erreur approprié.
Vous pouvez voir comment cela fonctionne lorsque vous avez vécu l'expérience de faire Laravel. Cependant, après tout, je vais utiliser la méthode intégrée du modèle et comment écrire le sort de la partie Modèle en premier lieu, et je ne me souviens pas à moins de le vérifier à chaque fois et de répéter régulièrement l'entrée et la sortie. J'ai ressenti la même chose que lorsque j'ai créé un portfolio. Puisque j'oserai participer au projet cette fois avec le niveau de compétence de Laravel sur l'étagère, je comprendrai Django et le niveau de compétence de la connaissance web qui l'accompagne afin que je puisse voler ne serait-ce qu'un peu de contribution et voler dans le plan. J'espère qu'il pourra être soulevé même un peu. Tout d'abord, jetez un œil au tutoriel officiel de Django.
Article qui permet le développement de système avec Django (Python) _Introduction Créer un environnement django avec docker-compose (MariaDB + Nginx + uWSGI) Python3.6 + NGINX + MariaDB10 + uWSGI Django Environment Greedy Set avec Docker-Compose Différences entre serveur Web et serveur d'applications dans le développement de Rails (traduction) Introduction à uWSGI À propos de «uWSGI» et du serveur d'applications J'expliquerai la différence entre le serveur Web et le serveur d'applications d'une manière facile à comprendre Quel est le rôle du serveur AP? Comprenons la différence avec le serveur Web