Django
Overview:
Django is Django.
Links:
End of extended support: 1.8 LTS -APR2018 1.11LTS -APR2020 2.0 -APR2019 Python3.4- 2.2 LTS Client template │ form [HTTP Req GET|POST] model │ │ urls -> [request] -> view -> [response] -> Client
django2.0:
RemovedInDjango20Warning: $ python -Wd manage.py
Project Files:
<DIR> ├── manage.py # Django Utilities ├── db.sqlite3 # DB ├── <SITE> # │ ├── settings.py # Django Settings │ ├── urls.py # URL Config │ └── wsgi.py # WSGI Config └── <APP> # ├── admin.py # Admin ├── apps.py # App ├── models.py # Model ├── tests.py # Test ├── urls.py # URL Config ├── views.py # View ├── migrations # │ └── 0001_initial.py # DB Migration Script ├── templates # Template Files │ └── <APP> # for Name Space │ └── base.html # html └── static # Static Files └── <APP> # for Name Space └── style.css # CSS
:
Create Project: $ django-admin startproject <SITE> ./ TimeZone Setting: file: <SITE>/setting.py DB Setting (MYSQL): file: <SITE>/setting.py DB Migration: $ python manage.py migrate Create App: $ python manage.py startapp <APP> Add App: file: <SITE>/setting.py Run Server: $ python manage.py runserver 0:8000 # from all PC Create Models: file: <APP>/models.py Updates DB Schema: $ python manage.py makemigrations <APP> $ python manage.py migrate Enable Admin Site: $ python manage.py createsuperuser file: <SITE>/admin.py file: <SITE>/urls.py
Install:
shel: $ pip install django $ python -m django --version
Create Project:
$ django-admin startproject <SITE> ./ > python myvenv\Scripts\django-admin.py startproject <SITE> . # win <DIR> ├── manage.py # Django Utilities └── <SITE> # ├── __init__.py # ├── settings.py # Django Settings ├── urls.py # URL Config └── wsgi.py # WSGI Config
TimeZone Setting:
file: <SITE>/setting.py edit: | LANGUAGE_CODE = 'ja-JP' TIME_ZONE = 'Asia/Tokyo' USE_TZ = False
DB Setting (MYSQL) (default:SQLite):
file: <SITE>/setting.py edit: | import pymysql pymysql.install_as_MySQLdb() DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': '<NAME>', 'USER': '<USER>', 'PASSWORD': '<PASS>', 'HOST': '', 'PORT': '', } } ENGINE: 'django.db.backends.sqlite3' 'django.db.backends.postgresql' 'django.db.backends.mysql' 'django.db.backends.oracle' NAME: os.path.join(BASE_DIR, 'db.sqlite3') CREATE DATABASE <NAME>;
DB Migration (Create Table):
$ python manage.py migrate <DIR> └── db.sqlite3
Create App:
$ python manage.py startapp <APP> <DIR> └── <APP> ├── __init__.py ├── admin.py ├── apps.py ├── models.py ├── tests.py ├── views.py └── migrations └── __init__.py file: <SITE>/settings.py edit: | INSTALLED_APPS = [ '<APP>.apps.<APP>Config' # <APP>.apps.py ]
Run Server:
$ python manage.py runserver # local PC only $ python manage.py runserver 0:8000 # from all PC # Log: $ python manage.py runserver --traceback 0:8000 # ??? $ python manage.py runserver 2>&1 | tee django.log # ???
Model:
pk: PrimaryKey SQL QuerySet
Updates DB Schema:
$ python manage.py makemigrations <APP> # Make Migration Script $ python manage.py migrate # Do Migrate
Enable Admin Site:
file: <SITE>/settings.py edit: | INSTALLED_APPS = [ 'django.contrib.admin', ] file: admin.py edit: | from django.contrib import admin from .models import <MODEL> admin.site.register(<MODEL>) file: urls.py edit: | from django.contrib import admin #admin.autodiscover() # ?? urlpatterns = [ path('admin/', admin.site.urls), ] $ python manage.py createsuperuser URL: http://127.0.0.1:8000/admin
Site urls:
file: <SITE>/urls.py edit: | from django.conf.urls import include, url urlpatterns = [ url(r'', include('<APP>.urls')), ]
App urls:
file: <APP>/urls.py edit: | from django.conf.urls import include, url from . import views urlpatterns = [ url(r'^$', views.post_list, name='post_list'), ]
view:
file: <APP>/view.py edit: | from .models import <MODEL> def post_list(request): return render(request, '<APP>/post_list.html', {'posts': <MODEL>})
Log:
file: <SITE>/settings.py edit: | LOGGING = { 'version': 1, 'formatters': { 'all': { # Format Name 'format': '\t'.join([ "[%(levelname)s]", "asctime:%(asctime)s", "module:%(module)s", "message:%(message)s", "process:%(process)d", "thread:%(thread)d", ]) }, }, 'handlers': { 'file': { # Handler Name 'level': 'DEBUG', 'class': 'logging.FileHandler', 'filename': os.path.join(BASE_DIR, 'django.log'), 'formatter': 'all', #'maxBytes': 1024 * 1024 * 10, # 10GBでローテーション #'backupCount': 10, # バックアップファイルは10ファイルまで }, 'console': { # Handler Name 'level': 'DEBUG', 'class': 'logging.StreamHandler', #'stream': sys.stdout, 'formatter': 'all' }, }, 'loggers': { 'command': { # Logger Name 'handlers': ['file', 'console'], 'level': 'DEBUG', #'propagate': True, }, }, } usag: from logging import getLogger logger = getLogger('command') # Logger Name 'command' logger.debug('DEBUG!!') # output
DJango App Packaging:
setuptools file: README.rst file: LICENSE file: setup.py file: MANIFEST.in edit: | include LICENSE include README.rst recursive-include docs * recursive-include <APP>/static * recursive-include <APP>/templates * $ python setup.py sdist $ pip install --user <APP>/dist/<APP>-0.1.tar.gz $ pip uninstall <APP> <DIR> ├── LICENSE # License Info ├── README.rst # Readme Info ├── MANIFEST.in # Include Files ├── setup.py # Setup └── <APP> # App Folder ├── static # └── templates #
:
{{ <VALUE> }} {% extends 'myapp/base.html' %} {% load staticfiles %} {% if user.is_authenticated %}{% else %}{% endif %} {% block content %}{% endblock %} {% for post in posts %}{% endfor %} {% csrf_token %}
:
model: Post(models.Model): - author = models.ForeignKey('auth.User') - title = models.CharField(max_length=200) - text = models.TextField() - created_date = models.DateTimeField(default=timezone.now) - published_date = models.DateTimeField(blank=True, null=True) site_urls: url(r'^admin/', admin.site.urls), url(r'^accounts/login/$', views.login, name='login'), url(r'^accounts/logout/$', views.logout, name='logout', kwargs={'next_page': '/'}), url(r'', include('myapp.urls')), app_urls: url(r'^$', views.post_list, name='post_list' ), url(r'^drafts/$', views.post_draft_list, name='post_draft_list'), url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail' ), url(r'^post/new/$', views.post_new, name='post_new' ), url(r'^post/(?P<pk>[0-9]+)/edit/$', views.post_edit, name='post_edit' ), url(r'^post/(?P<pk>\d+)/publish/$', views.post_publish, name='post_publish' ), url(r'^post/(?P<pk>\d+)/remove/$', views.post_remove, name='post_remove' ), view: post_list(request) - render(request, 'myapp/post_list.html', {'posts': posts}) post_draft_list(request) - render(request, 'myapp/post_draft_list.html', {'posts': posts}) post_detail(request, pk) - render(request, 'myapp/post_detail.html', {'post': post}) post_new(request) - redirect(post_detail, pk=post.pk) - render(request, 'myapp/post_edit.html', {'form': form}) post_edit(request, pk) - redirect(post_detail, pk=post.pk) - render(request, 'myapp/post_edit.html', {'form': form}) post_publish(request, pk) - redirect('post_detail', pk=pk) post_remove(request, pk) - redirect('post_list') template: base.html - <a href="{% url 'post_draft_list' %}"> - <a href="{% url 'post_new' %}"> - <a href="{% url 'login' %}"> - <a href="{% url 'logout' %}"> post_list.html post_draft_list.html post_edit.html post_detail.html - <a href="{% url 'post_publish' pk=post.pk %}"> - <a href="{% url 'post_edit' pk=post.pk %}"> - <a href="{% url 'post_remove' pk=post.pk %}">
URL Dispatcher:
file: settings.py ROOT_URLCONF = '<SITE>.urls' file: <SITE>.urls urlpatterns = [ path('', include('<APP>.urls')), path('admin/', admin.site.urls), ] URLパターンを順に調べ、最初にマッチしたところで from django.urls import include, path path(route, view, kwargs=None, name=None) path(route, include('app.urls')) re_path(route, view, kwargs=None, name=None) # (?P<name>pattern) url(regex, view, kwargs=None, name=None, prefix='') # name for reverse() # kwargs is dict-args url(regex, include('app.urls')) Path converters: - <str:name> # non-empty string, excluding the path separator, '/'. :default - <path:name> # non-empty string, including the path separator, '/'. - <int:name> # zero or any positive integer. Returns an int. - <slug:name> # slug-string (ASCII letters or numbers & '-','_') - <uuid:name> # a formatted UUID. To prevent multiple URLs from mapping to the same page, dashes must be included and letters must be lowercase. Returns a UUID instance. Custom path converter: Create Functions Regular expressions: 'r' # Python raw string, can't escape, only ¥" ¥' '^' # Begin '$' # End r'^$' # '' url(r'^$', views.index, name='index') r'^aaa/$' # 'aaa/' url(r'^aaa/$', views.aaa, name='aaa') (?P<name>pattern) # Named Capturing Group url(r'^(?P<pk>[0-9]+)/$', views.detail, name='detail') # pk <- [0-9]+