SlideShare a Scribd company logo
1 of 93
Download to read offline
スゴイ Django based on Django 1.11 and Python 3.6.n
makoto tsuyuki - UNCOVER TRUTH Inc.
Python&Djangoで始めるWeb開発 in 札幌 #1 2017.11.11
お前、誰よ
tsuyukimakoto a.k.a everes
鎌倉から来ました
django-ja 初代ドメインホルダー
最初に買ったPythonの本
「Pythonテクニカルリファレンス」
株式会社UNCOVER TRUTHで働
いてます。エンジニア探してま
す
https://www.uncovertruth.co.jp/ja/userdive/
djangoとの関わり
2005年7月から触ってます
2006年2月に4人でdjango-jaを始めました
2009年頃までDjango勉強会を開催してた
djangoとは?
Django Reinhardt
Web Application
Framework
Vs Ruby on Rails
Django beats …
Do you know Zope?
Django before 1.0
そもそもは2003年から
Django before 1.0
Django to be The Python Web Framework
by Guido van Rossum @SciPy2006
Full Stack
MVC vs MTV
Full Stack
MVC vs MTV
Model = Model
Full Stack
MVC vs MTV
View ≠ Template
Full Stack
MVC vs MTV
Controller ≠ View
Full Stack
Stable
ドキュメンテーションされたAPIが無くなる時は特定
のプロセスを経て消される
7年前のSoozyConのスライドを見返していたけれど
、当時と設計思想は変わっていない
Secure
NASA
Mozilla
jangoproject.com/en/dev/internals/security/#reporting-se
admin
RoRのScaffoldに対して、djangoにはadminがある
https://youtu.be/pkETpPayyFc
Fundamentals
設計思想
ルースカップリング
コード量の低減
迅速な開発
DRY (Don’t repeat yourself) 則
暗示的より明示的に
一貫性
https://docs.djangoproject.com/en/1.11/misc/design-philosophies/
API stability
• ドキュメンテーショ
ンされたAPがstable
• remain in the API for
at least two feature
releases.
https://docs.djangoproject.com/en/1.11/misc/api-stability/
HTTP
Requestを受けて
処理をして
Responseを返す
WSGI
Python Web Server Gateway Interface
PEP333, 3333
引数を2つ受け取るCallableを返す
1つ目はRequestに関する情報
2つ目はCallback
django.core.handlers.WSGIHandler あたりから追っていくと全体
が見えます
Request to Response
djangoのMiddleware
__call__ (Viewの実行前)
URLconfを使ってHandlerがURLに対応するViewを探す
process_view
Viewが実行される(Responseが生成される)
process_template_response
__call__ (Viewの実行後)
process_exception
>>> class A:
... def __call__(self):
... print('called!')
...
>>> a = A()
>>> a()
called!
>>> def outer():
... def inner():
... print('hello world')
... return inner
...
>>> o = outer()
>>> o()
hello world
デフォルトのMiddleware
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',
]
Request
ResponseView
blog/middlewares.py
hokkaido/settings.py
呼び出すと
first middlewqre before view
second middlewqre before view
django.core.handlers.BaseHandler._get_response: r
first middlewqre process_view
second middlewqre process_view
IndexView: get
second middlewqre process_template_response
first middlewqre process_template_response
second middlewqre after view
first middlewqre after view
Model
Modelに全部書く勢い
DBのテーブル作成に必要な情報も
入力チェックに必要な情報も
関連も書く
ビジネスロジック的なものも書く
blogアプリケーションのEntryモデル
ModelForm
>>> from blog.models import Entry
>>> from django.forms import ModelForm
>>> class EntryForm(ModelForm):
... class Meta:
... model = Entry
... excludes = ['created']
>>>
>>> form = EntryForm(dict(slug='test3', title='MF'))
>>> form.is_valid()
False
>>> form.errors
{'released': ['This field is required.'], 'author': ['This field is
required.’]}
ModelForm
>>> entry = Entry.objects.get(pk=1)
>>> form = EntryForm(instance=entry)
>>> form.as_ul()
'<li><label for="id_slug">Slug:</label> <input type="text" name="slug" value="test"
maxlength="50" required id="id_slug" /> <span class="helptext">Part of the URL describing the
content</span></li>n<li><label for="id_title">Title:</label> <input type="text" name="title"
value="北海道へ来ました!" maxlength="128" required id="id_title" /></li>n<li><label
for="id_released">Release date / time:</label> <input type="text" name="released"
value="2017-11-05 17:55:34" required id="id_released" /><input type="hidden" name="initial-
released" value="2017-11-05 17:55:34" id="initial-id_released" /></li>n<li><label
for="id_author">Author:</label> <select name="author" required id="id_author">n <option
value="">---------</option>nn <option value="1" selected>makoto</option>nn</select></li>'
manage.py shellで遊ぶ
$ python manage.py shell
>>> from blog.models import Entry
>>> from django.contrib.auth import get_user_model
>>> me =
get_user_model().objects.filter(email='mtsuyuki@gmail.com')[
0]
>>> me
<User: makoto>
manage.py shellで遊ぶ
>>> entry = Entry(slug='test', title='北海道へ来ました!',
author=me)
>>> entry.save()
/Users/makoto/venv/hokkaido/lib/python3.6/site-
packages/django/db/models/fields/__init__.py:1451:
RuntimeWarning: DateTimeField Entry.released
received a naive datetime (2017-11-05
17:55:34.238327) while time zone support is active.
RuntimeWarning)
manage.py shellで遊ぶ
>>> for entry in Entry.objects.all():
... print(f'{entry.pk} {entry.slug}: {entry.title} by
{entry.author.username}')
...
1 test: 北海道へ来ました! by makoto
manage.py shellで遊ぶ
>>> me.entry_set.all()[0].title
'北海道へ来ました!'
me は django.contrib.auth.models.User
manage.py shellで遊ぶ
>>> me.entry_set.create(slug='test2', title=‘meのEntry
を追加')
<Entry: Entry object>
>>> _.author
<User: makoto>
Queryset
Entry.objects.all()は条件が格納されたQuerysetのイン
スタンスを返します
🤔
Queryset
LOGGING = {
'version': 1,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
Queryset
>>> from blog.models import Entry
>>> qs = Entry.objects.all()
>>> list(qs)
(0.001) SELECT "blog_entry"."id", "blog_entry"."slug",
"blog_entry"."title", "blog_entry"."released",
"blog_entry"."created", "blog_entry"."author_id" FROM
"blog_entry"; args=()
[<Entry: Entry object>, <Entry: Entry object>]
Queryset - filter
>>> qs1 = qs.filter(slug='test')
>>> list(qs)
[<Entry: Entry object>, <Entry: Entry object>]
>>> list(qs1)
(0.000) SELECT "blog_entry"."id", "blog_entry"."slug",
"blog_entry"."title", "blog_entry"."released",
"blog_entry"."created", "blog_entry"."author_id" FROM
"blog_entry" WHERE "blog_entry"."slug" = 'test'; args=('test',)
[<Entry: Entry object>]
Queryset - exclude
>>> qs2 = qs.exclude(slug='test')
>>> list(qs2)
(0.000) SELECT "blog_entry"."id", "blog_entry"."slug",
"blog_entry"."title", "blog_entry"."released",
"blog_entry"."created", "blog_entry"."author_id" FROM
"blog_entry" WHERE NOT ("blog_entry"."slug" = 'test');
args=('test',)
[<Entry: Entry object>]
Queryset - 関連
>>> Entry.objects.filter(author__email='mtsuyuki@gmail.com')
(0.000) SELECT "blog_entry"."id", "blog_entry"."slug",
"blog_entry"."title", "blog_entry"."released",
"blog_entry"."created", "blog_entry"."author_id" FROM
"blog_entry" INNER JOIN "auth_user" ON
("blog_entry"."author_id" = "auth_user"."id") WHERE
"auth_user"."email" = 'mtsuyuki@gmail.com' LIMIT 21;
args=('mtsuyuki@gmail.com',)
<QuerySet [<Entry: Entry object>, <Entry: Entry object>]>
Queryset - exact
>>> qs.exclude(slug__exact='test')
(0.000) SELECT "blog_entry"."id", "blog_entry"."slug",
"blog_entry"."title", "blog_entry"."released",
"blog_entry"."created", "blog_entry"."author_id" FROM
"blog_entry" WHERE NOT ("blog_entry"."slug" = 'test') LIMIT 21;
args=('test',)
<QuerySet [<Entry: Entry object>]>
Queryset - Q
>>> from django.db.models import Q
>>> Entry.objects.filter(Q(slug='test')|Q(slug='test2'))
(0.001) SELECT "blog_entry"."id", "blog_entry"."slug", "blog_entry"."title",
"blog_entry"."released", "blog_entry"."created", "blog_entry"."author_id" FROM
"blog_entry" WHERE ("blog_entry"."slug" = 'test' OR "blog_entry"."slug" = 'test2')
LIMIT 21; args=('test', ‘test2')
<QuerySet [<Entry: Entry object>, <Entry: Entry object>]>
>>> Entry.objects.filter(Q(slug__contains='t')&Q(slug__contains='2'))
(0.000) SELECT "blog_entry"."id", "blog_entry"."slug", "blog_entry"."title",
"blog_entry"."released", "blog_entry"."created", "blog_entry"."author_id" FROM
"blog_entry" WHERE ("blog_entry"."slug" LIKE '%t%' ESCAPE '' AND
"blog_entry"."slug" LIKE '%2%' ESCAPE '') LIMIT 21; args=('%t%', '%2%')
<QuerySet [<Entry: Entry object>]>
Q(slug='test')|Q(slug='test2')
Q(slug__contains='t')&Q(slug__contains='2')
Queryset - and
>>> Entry.objects.filter(
slug='test', author__email__contains='gmail'
).exclude(
author__email__startswith='spam'
)
(0.000) SELECT "blog_entry"."id", "blog_entry"."slug",
"blog_entry"."title", "blog_entry"."released", "blog_entry"."created",
"blog_entry"."author_id" FROM "blog_entry" INNER JOIN
"auth_user" ON ("blog_entry"."author_id" = "auth_user"."id")
WHERE ("blog_entry"."slug" = 'test' AND "auth_user"."email" LIKE
'%gmail%' ESCAPE '' AND NOT ("auth_user"."email" LIKE
'spam%' ESCAPE '')) LIMIT 21; args=('test', '%gmail%', 'spam%')
<QuerySet [<Entry: Entry object>]>
Queryset - slice
>>> Entry.objects.all()[1]
>>> Entry.objects.all()[:1]
>>> Entry.objects.all()[1:2]
>>> Entry.objects.all()[::2]
Queryset - others…
annotate, order_by, reverse, distinct, values, values_list, dates,
datetimes, none, union, intersection, difference, select_related,
prefetch_related, extra, defer, only, using, select_for_update,
raw, Methods that do not return QuerySets, get, create,
get_or_create, update_or_create, bulk_create, count, in_bulk,
iterator, With server-side cursors, Without server-side cursors,
latest, earliest, first, last, aggregate, exists, update, delete,
as_manager, Field lookups, exact, iexact, contains, icontains, in,
gt, gte, lt, lte, startswith, istartswith, endswith, iendswith, range,
date, year, month, day, week, week_day, time, hour, minute,
second, isnull, search, regex, iregex, Aggregation functions,
expression, output_field, **extra, Avg, Count, Max, Min, StdDev,
Sum, Variance
https://docs.djangoproject.com/en/1.11/ref/models/querysets/
Inheritance - abstract
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
https://docs.djangoproject.com/en/1.11/topics/db/models/#abstract-base-classes
Id
name
age
home_group
Inheritance - separate
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs =
models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
https://docs.djangoproject.com/en/1.11/topics/db/models/#multi-table-inheritance
id
name
address
place_ptr_id
serves_hot_dogs
serves_pizza
1to1
MultiDB -
DATABASE_ROUTERS
class AuthRouter(object):
def db_for_read(self, model, **hints):
if model._meta.app_label == 'auth':
return 'auth_db'
return None
def db_for_write(self, model, **hints):
return None
def allow_relation(self, obj1, obj2, **hints):
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
return None
https://docs.djangoproject.com/en/1.11/topics/db/multi-db/#using-routers
Template
継承
プレゼンテーションとロジックの分離
冗長さを防ぐ
XML をテンプレート言語に使わない
プログラミング言語を作り直さない
Template - variables
{{ variable }}
Template - loop
{% for variable in some_list %}
…
{% empty %}
…
{% endfor %}
• forloop.counter
• forloop.counter0
• forloop.first
• forloop.last
• etc…
Template - if
{% if variable %}
…
{% elif variable2 > 0 %}
…
{% else %}
…
{% endif %}
Template - tag
{% for o in some_list %}
<tr class="{% cycle 'row1' 'row2' %}">
...
</tr>
{% endfor %}
https://docs.djangoproject.com/en/1.11/ref/templates/builtins/
Template - filter
{{ value|linebreaksbr }}
https://docs.djangoproject.com/en/1.11/ref/templates/builtins/
Template - inheritance
<html>
<head>{% block title %}プロジェクト名:{% endblock title %}</head>
<script type="text/javascript" src="common.js"></script>
{% block custom_js %}{% endblock custom_js %}
<body>
<div id="menu">{% block menu %}{% endblock menu %}</div>
<div id="content">{% block content %}{% endblock content %}</div>
<div id=”copyright”>{% block copyright %}everes{% endblock %}</div>
</body>
</html>
{% extends 'base.html% %}
{% block title %}{{ block.super }} アプリ名とか{% endblock title %}
{% block menu %}アプリレベルのメニューとか{% endblock menu %}
{% extends 'app/base.html' %}
{% block content %}内容内容内容無いよう{% endblock content %}
<head>{% block title %}プロジェクト名:{% endblock title %}</head>
{% block title %}{{ block.super }} アプリ名とか{% endblock title %}
{% block content %}内容内容内容無いよう{% endblock content %}
<head>{% block title %}プロジェクト名:{% endblock title %}</head>
<div id="content">{% block content %}{% endblock content %}</div>
base.html
app/base.html
app/some.html
View
簡潔性
リクエストオブジェクトの利用
ルースカップリング
GET と POST の使い分け
URLconf
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$',
views.article_detail),
]
https://docs.djangoproject.com/en/1.11/topics/http/urls/
URLconf
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$',
views.article_detail),
]
https://docs.djangoproject.com/en/1.11/topics/http/urls/
views.month_archive(request, ‘2017’, ’11’)
/articles/2017/11/
URLconf
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$',
views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-
9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
https://docs.djangoproject.com/en/1.11/topics/http/urls/
views.month_archive(request, year=‘2017’, month=’11’)
/articles/2017/11/
View - function based
import datetime
from django.http import HttpResponse
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
https://docs.djangoproject.com/en/1.11/topics/http/views/
View - class based
from django.views.generic.base import View
from django.http import HttpResponse
class IndexView(View):
def dispatch(self, request, year=None, month=None):
html = f'<html><body>{year}/{month}</body></html>'
return HttpResponse(html)
https://docs.djangoproject.com/en/1.11/topics/http/views/
View - class based
from django.views.generic.base import View
from django.http import HttpResponse
class IndexView(View):
def dispatch(self, request, year=None, month=None):
html = f'<html><body>{year}/{month}</body></html>'
return HttpResponse(html)
https://docs.djangoproject.com/en/1.11/topics/http/views/
rticles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', IndexView.as_v
View - class based
get
post
put
patch
https://docs.djangoproject.com/en/1.11/ref/class-based-views/base/#view
delete
head
options
trace
View - idiom
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import MyForm
def myview(request):
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
# <process form cleaned data>
return HttpResponseRedirect('/success/')
else:
form = MyForm(initial={'key': 'value'})
return render(request, 'form_template.html', {'form': form})
https://docs.djangoproject.com/en/1.11/topics/class-based-views/intro/#handling-forms-with-class-based-views
View - idiom
class MyFormView(View):
form_class = MyForm
initial = {'key': 'value'}
template_name = 'form_template.html'
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# <process form cleaned data>
return HttpResponseRedirect('/success/')
return render(request, self.template_name, {'form': form})
https://docs.djangoproject.com/en/1.11/topics/class-based-views/intro/#handling-forms-with-class-based-views
Generic View
TemplateView
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = "about.html"
>[0-9]{4})/(?P<month>[0-9]{2})/$', TemplateView.as_view(templat
Generic display views
DetailView
ListView
from django.views.generic.list import ListView
from articles.models import Article
class ArticleListView(ListView):
model = Article
https://docs.djangoproject.com/en/1.11/ref/class-based-views/generic-display/
Generic editing views
FormView / CreateView / UpdateView / DeleteView
https://docs.djangoproject.com/en/1.11/ref/class-based-views/generic-editing/
from django.views.generic.edit import CreateView
from myapp.models import Author
class AuthorCreate(CreateView):
model = Author
fields = ['name']
Signal
アプリケーション間で連携しつつルースカップリン
グに保つ
https://docs.djangoproject.com/en/1.11/topics/signals/
Signalをreceiveする
from django.db.models.signals import post_save
from django.dispatch import receiver
from myapp.models import MyModel
@receiver(post_save, sender=MyModel)
def my_handler(sender, **kwargs):
...
cs.djangoproject.com/en/1.11/topics/signals/#connecting-to-signals-sent-by-specific
Signalを独自定義する
import django.dispatch
pizza_done = django.dispatch.Signal(
providing_args=["toppings", “size"]
)
https://docs.djangoproject.com/en/1.11/topics/signals/#defining-and-sending-signals
Signalを独自定義する
https://docs.djangoproject.com/en/1.11/topics/signals/#defining-and-sending-signals
class PizzaStore(object):
def send_pizza(self, toppings, size):
pizza_done.send(sender=self.__class__,
toppings=toppings, size=size)
...
–本丸にたどり着いた
“ReUsable Application”
ProjectとApplication
Project
settings.py
urls.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^community/', include(‘app_a.urls')),
url(r'^contact/', include(‘app_b.urls’)),
]
Application
models.py
views.py
admin.py
apps.py
urls.py
templates (フォルダ)
Application - templates
models.py
views.py
admin.py
apps.py
urls.py
templates (フォルダ)
Application - urls.py
app_name = ‘blog'
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003,
name=‘special_case_2003’),
url(r'^articles/([0-9]{4})/$', views.year_archive,
name=‘year_archive’),
]
{% url ‘blog:year_archive' 2003 %}
Application - auth
from django.contrib.auth impor get_user_model
UserModel = get_user_model()
django.conf.global_settings
DEFAULT_FILE_STORAGE
FILE_UPLOAD_HANDLERS
MIDDLEWARE_CLASSES
SESSION_ENGINE
CACHES
AUTHENTICATION_BACKENDS
DEFAULT_EXCEPTION_REPORTER_FILTER
TEST_RUNNER
STATICFILES_STORAGE
STATICFILES_FINDERS
to see next
https://docs.djangoproject.com/
https://github.com/django/django/
https://sentry.io/https://github.com/getsentry/sentry
http://pinaxproject.com
https://djangopackages.or
g
2880
http://amzn.to/2hQU2Be
Two scoops djangoでググれば出てきますけどね
Any Question?

More Related Content

What's hot

Web scraping using scrapy - zekeLabs
Web scraping using scrapy - zekeLabsWeb scraping using scrapy - zekeLabs
Web scraping using scrapy - zekeLabszekeLabs Technologies
 
AIWolf programming guide
AIWolf programming guideAIWolf programming guide
AIWolf programming guideHirotaka Osawa
 
Jim Manico: Developer Top 10 Core Controls, web application security @ OWASP ...
Jim Manico: Developer Top 10 Core Controls, web application security @ OWASP ...Jim Manico: Developer Top 10 Core Controls, web application security @ OWASP ...
Jim Manico: Developer Top 10 Core Controls, web application security @ OWASP ...Xlator
 
TangoWithDjango - ch8
TangoWithDjango - ch8TangoWithDjango - ch8
TangoWithDjango - ch8Asika Kuo
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programingwahyuseptiansyah
 
Secret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you aboutSecret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you aboutDror Helper
 
The Django Book, Chapter 16: django.contrib
The Django Book, Chapter 16: django.contribThe Django Book, Chapter 16: django.contrib
The Django Book, Chapter 16: django.contribTzu-ping Chung
 
Deploying
DeployingDeploying
Deployingsoon
 
4시간만에 따라해보는 Windows 10 앱 개발 샘플코드
4시간만에 따라해보는 Windows 10 앱 개발 샘플코드4시간만에 따라해보는 Windows 10 앱 개발 샘플코드
4시간만에 따라해보는 Windows 10 앱 개발 샘플코드영욱 김
 
Hibernate Tutorial for beginners
Hibernate Tutorial for beginnersHibernate Tutorial for beginners
Hibernate Tutorial for beginnersrajkamal560066
 
Delivering a Responsive UI
Delivering a Responsive UIDelivering a Responsive UI
Delivering a Responsive UIRebecca Murphey
 
201204 random clustering
201204 random clustering201204 random clustering
201204 random clusteringpluskjw
 
Introduction to jQuery - The basics
Introduction to jQuery - The basicsIntroduction to jQuery - The basics
Introduction to jQuery - The basicsMaher Hossain
 

What's hot (20)

Architecure components by Paulina Szklarska
Architecure components by Paulina SzklarskaArchitecure components by Paulina Szklarska
Architecure components by Paulina Szklarska
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
Web scraping using scrapy - zekeLabs
Web scraping using scrapy - zekeLabsWeb scraping using scrapy - zekeLabs
Web scraping using scrapy - zekeLabs
 
AIWolf programming guide
AIWolf programming guideAIWolf programming guide
AIWolf programming guide
 
greenDAO
greenDAOgreenDAO
greenDAO
 
Jim Manico: Developer Top 10 Core Controls, web application security @ OWASP ...
Jim Manico: Developer Top 10 Core Controls, web application security @ OWASP ...Jim Manico: Developer Top 10 Core Controls, web application security @ OWASP ...
Jim Manico: Developer Top 10 Core Controls, web application security @ OWASP ...
 
TangoWithDjango - ch8
TangoWithDjango - ch8TangoWithDjango - ch8
TangoWithDjango - ch8
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing
 
Secret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you aboutSecret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you about
 
J query training
J query trainingJ query training
J query training
 
The Django Book, Chapter 16: django.contrib
The Django Book, Chapter 16: django.contribThe Django Book, Chapter 16: django.contrib
The Django Book, Chapter 16: django.contrib
 
Deploying
DeployingDeploying
Deploying
 
BVJS
BVJSBVJS
BVJS
 
UI testing in Xcode 7
UI testing in Xcode 7UI testing in Xcode 7
UI testing in Xcode 7
 
Server1
Server1Server1
Server1
 
4시간만에 따라해보는 Windows 10 앱 개발 샘플코드
4시간만에 따라해보는 Windows 10 앱 개발 샘플코드4시간만에 따라해보는 Windows 10 앱 개발 샘플코드
4시간만에 따라해보는 Windows 10 앱 개발 샘플코드
 
Hibernate Tutorial for beginners
Hibernate Tutorial for beginnersHibernate Tutorial for beginners
Hibernate Tutorial for beginners
 
Delivering a Responsive UI
Delivering a Responsive UIDelivering a Responsive UI
Delivering a Responsive UI
 
201204 random clustering
201204 random clustering201204 random clustering
201204 random clustering
 
Introduction to jQuery - The basics
Introduction to jQuery - The basicsIntroduction to jQuery - The basics
Introduction to jQuery - The basics
 

Similar to スゴイ django - Python&Djangoで始めるWeb開発 in 札幌 #1

Custom web application development with Django for startups and Django-CRM intro
Custom web application development with Django for startups and Django-CRM introCustom web application development with Django for startups and Django-CRM intro
Custom web application development with Django for startups and Django-CRM introMicroPyramid .
 
Introduction To Django (Strange Loop 2011)
Introduction To Django (Strange Loop 2011)Introduction To Django (Strange Loop 2011)
Introduction To Django (Strange Loop 2011)Jacob Kaplan-Moss
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to DjangoJoaquim Rocha
 
Hands on django part 1
Hands on django part 1Hands on django part 1
Hands on django part 1MicroPyramid .
 
Django tutorial 2009
Django tutorial 2009Django tutorial 2009
Django tutorial 2009Ferenc Szalai
 
준비하세요 Angular js 2.0
준비하세요 Angular js 2.0준비하세요 Angular js 2.0
준비하세요 Angular js 2.0Jeado Ko
 
How to Mess Up Your Angular UI Components
How to Mess Up Your Angular UI ComponentsHow to Mess Up Your Angular UI Components
How to Mess Up Your Angular UI Componentscagataycivici
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
Django - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazosDjango - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazosIgor Sobreira
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점 Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점 WebFrameworks
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점Jeado Ko
 
Django for Beginners
Django for BeginnersDjango for Beginners
Django for BeginnersJason Davies
 

Similar to スゴイ django - Python&Djangoで始めるWeb開発 in 札幌 #1 (20)

Custom web application development with Django for startups and Django-CRM intro
Custom web application development with Django for startups and Django-CRM introCustom web application development with Django for startups and Django-CRM intro
Custom web application development with Django for startups and Django-CRM intro
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
Django
DjangoDjango
Django
 
Django Show
Django ShowDjango Show
Django Show
 
Building Advanced XSS Vectors
Building Advanced XSS VectorsBuilding Advanced XSS Vectors
Building Advanced XSS Vectors
 
Introduction To Django (Strange Loop 2011)
Introduction To Django (Strange Loop 2011)Introduction To Django (Strange Loop 2011)
Introduction To Django (Strange Loop 2011)
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
Hands on django part 1
Hands on django part 1Hands on django part 1
Hands on django part 1
 
Django tutorial 2009
Django tutorial 2009Django tutorial 2009
Django tutorial 2009
 
Django
DjangoDjango
Django
 
준비하세요 Angular js 2.0
준비하세요 Angular js 2.0준비하세요 Angular js 2.0
준비하세요 Angular js 2.0
 
Mini Curso de Django
Mini Curso de DjangoMini Curso de Django
Mini Curso de Django
 
How to Mess Up Your Angular UI Components
How to Mess Up Your Angular UI ComponentsHow to Mess Up Your Angular UI Components
How to Mess Up Your Angular UI Components
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
Django - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazosDjango - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazos
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점 Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
 
Django for Beginners
Django for BeginnersDjango for Beginners
Django for Beginners
 
Django web framework
Django web frameworkDjango web framework
Django web framework
 
pyscript_django.pdf
pyscript_django.pdfpyscript_django.pdf
pyscript_django.pdf
 

More from makoto tsuyuki

Erulolo at Kamakurago #1
Erulolo at Kamakurago #1Erulolo at Kamakurago #1
Erulolo at Kamakurago #1makoto tsuyuki
 
Webフレームワークパネル(Django) at PyConJP 2012
Webフレームワークパネル(Django) at PyConJP 2012Webフレームワークパネル(Django) at PyConJP 2012
Webフレームワークパネル(Django) at PyConJP 2012makoto tsuyuki
 
Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3makoto tsuyuki
 
引き出しとしてのDjango - SoozyCon7
引き出しとしてのDjango - SoozyCon7引き出しとしてのDjango - SoozyCon7
引き出しとしてのDjango - SoozyCon7makoto tsuyuki
 
Python Workshop the Edge - django
Python Workshop the Edge - djangoPython Workshop the Edge - django
Python Workshop the Edge - djangomakoto tsuyuki
 
伝説のギタリストじゃない方のDjango
伝説のギタリストじゃない方のDjango伝説のギタリストじゃない方のDjango
伝説のギタリストじゃない方のDjangomakoto tsuyuki
 
変態的PHPフレームワーク rhaco
変態的PHPフレームワーク rhaco変態的PHPフレームワーク rhaco
変態的PHPフレームワーク rhacomakoto tsuyuki
 

More from makoto tsuyuki (10)

Erulolo at Kamakurago #1
Erulolo at Kamakurago #1Erulolo at Kamakurago #1
Erulolo at Kamakurago #1
 
Not free
Not freeNot free
Not free
 
Testman
TestmanTestman
Testman
 
Webフレームワークパネル(Django) at PyConJP 2012
Webフレームワークパネル(Django) at PyConJP 2012Webフレームワークパネル(Django) at PyConJP 2012
Webフレームワークパネル(Django) at PyConJP 2012
 
Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3Django - 次の一歩 gumiStudy#3
Django - 次の一歩 gumiStudy#3
 
引き出しとしてのDjango - SoozyCon7
引き出しとしてのDjango - SoozyCon7引き出しとしてのDjango - SoozyCon7
引き出しとしてのDjango - SoozyCon7
 
Python Workshop the Edge - django
Python Workshop the Edge - djangoPython Workshop the Edge - django
Python Workshop the Edge - django
 
伝説のギタリストじゃない方のDjango
伝説のギタリストじゃない方のDjango伝説のギタリストじゃない方のDjango
伝説のギタリストじゃない方のDjango
 
変態的PHPフレームワーク rhaco
変態的PHPフレームワーク rhaco変態的PHPフレームワーク rhaco
変態的PHPフレームワーク rhaco
 
継承だろJK
継承だろJK継承だろJK
継承だろJK
 

Recently uploaded

The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...kalichargn70th171
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxRTS corp
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxSasikiranMarri
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptxVinzoCenzo
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsJean Silva
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfkalichargn70th171
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldRoberto Pérez Alcolea
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorTier1 app
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfRTS corp
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogueitservices996
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingShane Coughlan
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slidesvaideheekore1
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...Bert Jan Schrijver
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLionel Briand
 
Mastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptxMastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptxAS Design & AST.
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shardsChristopher Curtin
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfmaor17
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jNeo4j
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...OnePlan Solutions
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics
 

Recently uploaded (20)

The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptx
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptx
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero results
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository world
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryError
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogue
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
 
Introduction to Firebase Workshop Slides
Introduction to Firebase Workshop SlidesIntroduction to Firebase Workshop Slides
Introduction to Firebase Workshop Slides
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
 
Large Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and RepairLarge Language Models for Test Case Evolution and Repair
Large Language Models for Test Case Evolution and Repair
 
Mastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptxMastering Project Planning with Microsoft Project 2016.pptx
Mastering Project Planning with Microsoft Project 2016.pptx
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards
 
Zer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdfZer0con 2024 final share short version.pdf
Zer0con 2024 final share short version.pdf
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
 

スゴイ django - Python&Djangoで始めるWeb開発 in 札幌 #1

Editor's Notes

  1. 最初に買ったPythonの本はピアソンから日本語訳が出ていたPythonテクニカルリファレンスでした。Python1.5.2ベースでした。 今は東京渋谷区初台のUNCOVER TRUTHという会社でheatmapツール作ってます。
  2. - Django Reinhardtというジプシージャズってジャンルになるんですかね。ギタリストです。 フレームワークを作ったAdrianという人がギターを弾くんですけど、きっとファンなんでしょうね この本を出す時に編集さんがどうしてもちゃんとDjango Reinhardtの絵を使いたいんだと言ってアメリカのエージェントに問い合わせたりしてました。今はアスキードワンゴでブイブイ言わせて技術書作ってる人なんですけど、実はPython使いなんです。
  3. はい。djangoはWebアプリケーションフレームワークと呼ばれるものです そもそもはみんな同じようなコード書くし、おんなじように書いたら楽できるようにしようよ、というのがフレームワークです Webの場合は、HTTPというプロトコルに乗って入力を検査してデータを操作して何かを表示する、というのをベースにしつつ、面倒なファイルのアップロードとか、データを登録した後の画面でリロードしたらもう一個データが登録されるとか、気にしないといけないことが多くなってきてだるくなってたんですよね。JavaのStrutsとかTurbineあたりからフレームワークってのが普及し始めたんだと思います。
  4. そして、空前のRuby on Railsブームが2004年頃から始まった直後の2005年の7月にPythonはdjangoだぜ!という煽りとともに出てきました
  5. ところで、Zopeってご存知の方いらっしゃいますか? Zopeは20世紀からObject databaseを内部にもった統合開発環境兼アプリケーションサーバー兼CMSフレームワーク、という重厚な夢みたいな奴だったんですね。当時のPythonのWeb関係は、Zopeの1強で、他には有象無象のWebアプリケーションフレームワークが乱立していて誰も使ってない状況だったんです。それを打ち破ったのがdjangoなんです。自分もZopeに惹かれてPythonを選択したのでZopeは今でもすごいと思ってるのですが、Zopeの上に乗るPloneというCMSのお化けと合わさったらもう、コード書き始めるまでにどんだけ文書読めば良いんですか?読んでも理解できないんですけど!みたいな格好いい世界だったんです。Pythonに人を惹きつける力を持ちつつ、PythonのWebでの普及を妨げていたような、そんなZopeの一強時代をdjangoは終了させたんです。日本でのPythonの普及にも一躍かったと思ってますけど、実際はそうでもないですかね、どうでしょう。
  6. まず、これだけでスゴイという気持ちがいっぱいなんですけど、おっさんしか喜ばないスゴイ話はこれくらいにしましょうかね。Zopeについて話し始めると15年くらいPython触ってる人たちはみんな興奮しちゃうんです。 えー、djangoはそもそもは2003年くらいからとあるアメリカの新聞社の社内フレームワークとして開発が始まったようです。Railsが流行ってたので流れに乗ってオープンソースにした感じです。
  7. さて、Pythonの標準モジュールにjsonってモジュールあるのご存知ですか?あのモジュール、元々はsimplejsonというサードパーティ製のモジュールだったんですけど、みんなこれ使うし標準に入ってても良いよね、とPython2.6から標準モジュールにjsonモジュールという名前で取り込まれたんです。というような方針がPythonにあるんです。標準ライブラリになってれば似たモジュールが乱立しないしという感じですかね。 2006年にGuido、あ、GuidoはPythonの作者ですね。Perlでいうラリーウォール、RubyでいうMatzがGuidoです 2006年にGuidoがDjangoはPythonの標準フレームワークになっても良いくらいだよね、と発言しています。実際はリリースサイクル違いすぎるしそんなことしないけどね、はははーというやつです。(6:30)
  8. djangoの特徴で最初に出てくるのはFull Stackだということです WebのフレームワークでFull Stackというと、ミニマムはMVCが揃ってることかなー?と思うんですけど、djangoはこのMVCのことをMTVと呼んでいます。
  9. Mがモデルだというのは特に異論ない感じで。djangoの場合はMはPythonのObjectと、DatabaseをMappingするO/R Mapperと呼ばれる性格を持っています
  10. MVCのV、つまりViewというプレゼンテーションロジックに関わる部分をDjangoではTemplateのTで表します まぁ、表示なんでTemplateだって言われれば、まぁ
  11. MVCのC、つまりControllerのはずなんですが、DjangoではViewと呼んでいます djangのビューはtemplateに出力するものを集めてくるものだそうです ここの呼び名で混乱するとよくわからなくなるので、よくあるControllerっぽいものがViewだとしっかり覚えてください ちなみに、Controllerはどこにいるんだ?となると思いますが、djangoにはURLconfというURLとこのViewを関連づけるものがありまして、おそらくそれがControllerに当たるのかなーと思ってます。振り分けやるのはそこなんで。
  12. Pythonにはパッケージという名前空間がありまして、djangoの一部を抜き出して見ました した2つの濃い緑の部分はController的な部分と言える基本的な仕組みを実現しているところ 薄緑の部分は、O/Rマッパとテンプレートエンジン。先ほどのMTVでいうMとTですね。一応、薄緑の部分は取り替えられることになってます。 通常、フルスタックの概念的にはこの部分までで良いと思うのですが、Djangoが変わっているのはその上にあるオレンジ色の部分なんです ここまでをスタックしたのはおそらくDjangoが最初じゃないかと思います。(8:45)
  13. djangoの特徴として言われるのはFull Stackなんですが、実際にずっと見てきて感じるのはすごくステーブルだということです 一旦公開されたAPIがなくなる場合には、特定のプロセスを経て消されます。急にこのバージョンからなくなりました!ということはないんです。この辺もPythonっぽい気がします。 業務でDjangoを使ってるんですが、定期的にDjangoすげーよなー、という話題になります。 そもそも10年以上メンテし続けられているというのだけでもすごいんですが、今回実は7年前にPerlの人にdjangoを紹介してくれって言われた時に使った資料を見返してたんですけども、思想が変わってないんですよね。実装は相当変わってますけど。 Python3対応の時も、Python3用にスクラッチしてそこから2でも動く様にバックポートしたとか後方互換性の維持にかける猛烈な気合が感じられます。あ、ちなみに来年あたりに出るdjango2.0でPython2系のサポートが打ち切られます。1.8がLTSなのでサポートはしばらく存在しているとはいえ、もう2系を使ってるとテンパるので3系を使っていきましょう!(10:00)
  14. 実はかなり大事な特徴として、非常にセキュアに保たれてるというのも特徴でしょう NASAって結構Pythonを使ってくるんですけど、今はDjangoを使っているらしいです。 MozillaもDjangoを使っているっぽくて、 NASAとMozillaがガンガンセキュリティイシューをぶっこんでくるのでだいぶセキュアっぽいです djangoはかなり初期の頃からセキュリティイシューの報告フローも整備されていました 確か、Railsの脆弱性について誰かがブログに書いてしまってゼロデイ発生したとかそういう時代でした Djangoに限らず、脆弱性はウェーイってする前にちゃんと隠れて報告しましょうね このURLに脆弱性の報告の仕方が書かれているので見つけてしまったらコントリビュートしていきましょう(11:00)
  15. これだけだと寂しいので、少し派手めなところを 後で出てくるDjangoの設計思想にコード量の低減というものがあるのですが、Scaffoldはその思想と合わないので、djangoはadminというものをアイキャッチにしていました せっかくなので、ライブコーディングを、と思いましたが、開始からの時間がわからなくなるのと動かなかったら恥ずかしいのであらかじめプロジェクトの作成からadminのところまでビデオを撮って来ました。(11:30)
  16. adminのビデオ
  17. (18:00) 今見たadminはdjangoのいろいろなコンポーネントの組み合わせでできています。adminの仕組みに則って細かくカスタマイズをしたりといったことは当然できますが、今見たところについては自分で作ったblogアプリケーションのEntryモデルをadminから利用しますという宣言を、blogアプリケーション内でしただけです。 このadminというものもdjangoのアプリケーションという概念のものです。 ここからdjangoを構成するものを見ていきましょう。
  18. PythonのREPLでimport thisってやったことがある人、どのくらいいますか? まぁ、あれはギャグなんですけど、djangoはドキュメントに設計哲学というか思想というかが書いてあります 実際に実務で使っていると、よくできてんなーと何ヶ月かに一度呟いてしまうわけですが、この思想に照らし合わせてもずれがないというか、だからこそうまく回ってるんだなーとなることが多いです。 Djangoはフルスタックなんですが、それぞれのコンポーネントのことを意識しないということが徹底されています。例えば、InstagramはDjangoを使っているのですが、ORMapperは使っていないそうです。Facebookのなんとかっていうバックエンドを使うからだそうですけど。 あとはDRYだけどちゃんと書く。これもメンテナンス性を考えると大事なんですよね。 自動生成でもコードはコードなので無駄なものは自動生成しない、定義から動的にできるものは動的にする、これはコード量の低減っていう思想のところですね。adminもモデルの定義を使って動的に動作しますが、adminで利用するということはちゃんと明示的に書きますし、Entry自身のtitleは128文字までというようなことも1箇所に書いたらテーブルの生成でも入力のvalidationでも使われるわけです。
  19. たとえ自動生成でも、コードが存在したらメンテナンスを行わないといけなくなります。djangoがコードの低減という思想を持っているのはできるだけメンテナンスするコードを減らしたいという運用を考えてのことなのです。 そして、安定しているという話と、メンテナンス性という話に絡むのですが、 ドキュメンテーションされたAPIは少なくともdeprecatedとしてマークされてから2つのfeatureリリースの間は維持されることになっています featureリリースは基本的には8ヶ月に1度出ることになっているので、1年以上は猶予があることになります deprecatedになったという情報はrelease noteに記載される他、バージョン幾つで消えるというdeprecated warningを出すオプションをつけて実行するとウォーニング情報が出力されるようにもなっています
  20. HTTPの世界はRequestを受けて、処理をして、Responseを返す これが基本ですね。繋がりっぱなしになったりとかもあると思いますが、まぁ、それはまた別で。
  21. JavaでいうところのServlet APIにあたるWebアプリケーションに関するインターフェース仕様です ウィスキーと呼びます apacheのmod_wsgiというモジュールを経由するか、nginxからuwsgiといったアプリケーションサーバーを経由してdjangoのアプリケーションを呼び出します
  22. Requestが飛んで来て、Responseになって返っていきます。 ややこしいのですが、WSGIを使っている場合には最初にWSGIのMiddlewareを通ります Middlewareというのは、Requestの処理前と、Responseを返す前に処理を挟む機構です
  23. djangoのmiddlewareはmiddlewareごとに5箇所の処理を挟める場所があります。 上から見ていくと、まずリクエストが飛んで来ると呼び出されます。__call__は大丈夫ですか?() 例えば高階関数の場合、返した関数の後ろにカッコをつけて呼び出したりしますよね?() それと同じでクラスを生成したインスタンスの後ろにカッコをつけて呼び出すとこの__call__が呼ばれます。(23:30)() そして、URLから対応するViewを探した後、そしてViewの実行前に process_view というメソッドが呼ばれます 次に、Viewの実行後、templateを使ってrenderingするresponseがViewから返って来た場合に動作するprocess_template_response レスポンスを返す前に __call__ でまだ処理ができます それから、例外が発生した時に動作する process_exception
  24. 自動生成されたsettings.pyという設定ファイルにあらかじめ記載されているdjangoのMiddlewareです セキュリティ関係のMiddlewareやHTTPセッション、それからAuthenticationに関するものなどがあります AuthenticationMiddlewareが刺さっていると、Viewにたどり着いた時にrequestというオブジェクトにログインしているユーザーの情報が入っていたりといったことに使います。() MiddlewareはViewが実行される前までは設定順に、Viewが実行されてResponseを扱うものは設定の逆順に実行されていきます
  25. 例えばこういうMiddlewareがあったとします。 2つですが、それぞれfirstなのかsecondなのかをprintするだけです 実際は、Middlewareのクラスがインスタンス化されて、そのインスタンスを引数にrequestを渡して呼び出すんです するとその中でインスタンス化する際に渡されていたget_responseというメソッドを呼び出す決まりになってるんですが、このget_responseは中でURLとViewのマッチングを行って、Viewを呼び出して、そのViewを呼び出す前後でprocess_viewとか諸々を呼び出していると、そういうことなんです。
  26. で、settings.pyのMIDDLEWAREという設定に、今定義した2つのmiddlewareを追加してみます。
  27. 先ほどの、Requestは設定順、Responseは設定の逆順、というのはこういうことです まず、__call__が呼び出されます そして、get_responseというのが__call__の中で呼び出されるんでしたよね。その中でURLとViewのマッチングが行われます URLとViewのマッチングが終わると、Viewの呼び出し前に process_view というMiddlewareのメソッドが呼ばれます 続いてViewが実行されて、ここからはResponseを処理するMiddlewareのメソッドです Templateが使われる場合には process_template_response 最後に__call__を抜ける前の処理です(28:00)
  28. 何度か言っているように、djangoはモデルに多くのことを書きます
  29. モデルは、django.db.models.Modelクラスを継承して定義します クラスにベロっと書いてある変数はクラス変数ですけど、大丈夫ですかね? インスタンスの変数はメソッドとかイニシャライズメソッドでself.title、みたいにします 横道に逸れました、slugというのは日本語だとあまり意味がないんですけど、例えばtitleからURLに使えない文字を省いてURLに使うみたいな用途のフィールドです。他にも文字フィールドだとか、日付フィールドだとか、FKのフィールドだとかいう定義をしています。このモデルを通じて、データベースを操作できます。
  30. ModelFormを使うとModelの定義を元に入力フォームを作れます ModelFormはMetaという内部クラスに設定を定義します。モデルは先ほどのEntryを使って、フィールドのうちcreatedはフォームに含めません、という定義をしています。 通常はHttpRequestのPOST情報を使うのですが、例では辞書にslugとtitleを設定してEntryFormを生成しています。 EntryFormのインスタンスにはデータの検証用メソッドがあります。releasedとauthorが必須のフィールドなので、検証メソッドはFalseを返し、エラー情報を見るとreleasedとauthorは必須だというエラーが格納されています。 入力データが正しい場合には、formのsaveメソッドを呼べばデータをデータベースに保存できます。
  31. formはいくつかのパターンでHTMLを出力できるほか、fieldを順に取り出してHTMLを生成したりもできます。 FieldとかWidgetもテンプレートで制御されているので、出力の上書きをしたりもできます。formに値がセットされていなければ当然空っぽのHTML Formが出力されますし、あらかじめ選択されていたりデータが渡されていたりするとちゃんとHTML Formにも埋まった状態で出力できます。
  32. (31:00) このmanage.py shellというのは有用なので、是非覚えておいてください。 adminを見てみた動画の中では、python manage.py runserverとして開発サーバーを起動しました このmanage.py shellを使うとdjangoのプロジェクトを有効にした状態でREPLを使えます 先ほど書いた Entry モデルをimportして、FKに使うためのユーザーのモデルもimportします。authenticationとかユーザーのモデルも差し替えられるようになっているので、直接モデル名を指定せずに関数を使ってモデルクラスをimportしてます。 今のところあまり気にしないで良いのですけどごめんなさい
  33. モデルに必要な情報を渡してインスタンスを生成して、saveというメソッドを呼ぶとデータが保存されます。 ウォーニングが出てしまっているのはモデル定義でtimezoneのあたりをサボったからです。 本当はdjango.utils.timezoneのnowを使わないといけないんですけどすのdatetimeを使ってしまいました。 とりあえず気にせずに。真似するとウォーニングが出るので一応ウォーニングも載せておいた感じです。(32:30)
  34. モデルクラス、ドット、objects、ドット、allとしています。 このobjectsは、モデルクラスのマネージャーと呼ばれるものです モデルクラスは、誤解を恐れずに言えば1レコードを マネージャーは集合に対する操作をするものです とあるActive RecordよりActive Recordっぽいと勝手に思ってます。 このobjectsはモデルの定義には出て来ませんでした。モデルに定義がない場合にはobjectsという名前ではやされる事になっています。メソッドミッシング的なものではなくて、起動時にモデルをチェックして存在しなければデフォルトマネージャーというものが追加されます。 このマネージャーはあらかじめ集合の抽出条件を絞り込んだものを作ったりできます。例えば、activeフラグのたったデータだけを抽出するactive_objectsみたいな名前のマネージャーをモデルに追加しておけばミスが減るでしょうし、同じ絞り込みを毎回書く必要がなくなります。
  35. ところで、Entryのauthorにmeを指定して保存しました。このmeはdjango.contrib.auth.models.Userというモデルのレコードです。blogアプリケーションのモデルではなくて、django.contrib.authというアプリケーションのモデルです。djangoはFKで関連があると、逆方向の関連を扱うマネージャーを生やしてくれます。entryというモデルからUserモデルにFKを張っているので、User1に対してEntryはnです。ですから、me.entry_setというRelatedManagerが生えています。このRelatedManagerはあらかじめauthorがmeに絞られたManagerです。
  36. このRelatedManagerを使うと、authorを指定せずとも自動でauthorが指定されたEntryを追加できます。 あ、REPLのアンスコは良いですか?直前の結果が格納されます。(35:44)
  37. Entry.objects.all()は条件が格納されたQuerysetのインスタンスを返します… …? なんのこっちゃわからないと思いますので、SQLが発行された時にログが出るようにしてみます
  38. - settings.pyにログの設定をします。この設定はぐぐれば出てくるんで。
  39. - Entry.objects.all()の結果をqsという変数に格納した時点ではSQLは発行されていません。強制的にlistにした際にSQLが発行されています。つまり、for文で回す時などに発行されます。ちなみに、listすると当然listになりますが、for文で回す文にはiteratorになっているのでレコード数が多めでもなんとかなります。(36:30)
  40. 続いて先ほどEntry.objects.all()のQuerysetを格納したqsという変数に対して、filterというメソッドを呼んでみます。filterは検索条件を指定するメソッドです。今回はslugがtestのものを対象にする条件設定です。結果はqs1という変数に格納しました。 試しにもう一度qsをlistして見ると、先ほどと同じ結果がSQLを発行せずに出力されました。 qs1をlistして見ると、条件の絞られたSQLが発行されて結果は1件に減りました。 これはQuerysetオブジェクトにfilterメソッドで条件を追加したら、元のQuerysetは変更されず、新しいQuerysetオブジェクトが返ってくるという事です。(37:40) このSQLのデバッグはちょっとドキドキするかもしれませんが、ちゃんとDBAPIのバインディングスを使っているはずなのであえてrawというやつで生SQLを発行する時以外は心配しないで良いです。
  41. 今度はqsに対して、notの条件を指定するexcludeメソッドを使ってみました。 SQLはNOTのSQLになっていますね
  42. FKなどの関連をjoinして別テーブルのフィールドを条件に使うのも簡単にできます。 EntryモデルのauthorというFKのフィールドの先にあるテーブルのemailというフィールドに対して検索するにはauthorの後に__でフィールドをつなぎます。FK先のFK先のと複数テーブルをjoinもできます。
  43. 今までたんにフィールドイコール値で書いていたのは、exactという一致を条件にするものでした。条件はフィールドに続けてアンスコを二つ書いて条件を指定します。
  44. だんだん文字が小さくなって来ました! 同じフィールドに対してor条件やand条件を書く場合にはQという条件クラスを使い、orの場合にはパイプを、andの場合にはアンパサントを使ってつなぎます これはすごくPythonっぽい気がします。パイプやアンパサは演算子の上書きで実現しています。
  45. 別のフィールドに対してであれば一つのfilterの中に複数の条件をかけます filterとexcludeは同じフィールドに対してでもSQLと同じようなイメージで書けますね
  46. それぞれ期待通りに動作します ただし、ネガティブなインデックスは使えません。reverseなどを使う必要があります。 これもPythonっぽいです。この書き方がQueryset評価時にSQLに化けるわけです。
  47. DjangoのQuerysetはかなりのところまでSQLを表現できます 1.11からはUNIONやIntersectionなどにまで対応をしていてギョエーという感じです 2.0ではウィンドウ関数も使えるようになるようですよ これを全部見ていくとそれだけで1日かかってしまうので割愛します。(40:00)
  48. モデルの継承には2種類あります モデルクラスの内部Metaクラスにabstract=Trueとするとこのモデルに対応するテーブルは作られず、実際は子供のモデルテーブルにカラムが追加されます。 右側の四角がテーブルのイメージですね あ、ちなみにidは定義してないのに生成されます。 明示的に書くんだ、書くんだ、と言いながらPrimaryKeyに関しては書かなければ暗黙でidという名前で定義されます PrimaryKeyFieldの定義があればそちらが優先されます。pkという別名ガーとか色々便利な感じになっているのでその辺りは実際に触ってみてください。 それから、多くのORMapperと同様に、複合PKは扱えません。
  49. 別のモデルを継承すると、自動で1to1の関連が作られます。 実際に利用する際はRestaurantのインスタンスでPlaceのフィールドを参照できます。
  50. 複数のデータベースも利用できます readの場合、writeの場合、複数データベースにまたがる場合には関連のFKをはれるかなどの条件を判断するRouterと呼ばれるクラスを定義します このRouterはいくつも定義して条件にマッチするまで設定されたRouterをみていきます。どれかの条件にマッチしてsettingsに定義してあるデータベースの名前を返したら終わりです。(42:20)
  51. テンプレートはhtmlやメールといったテキストを出力するためのものです 最近は継承が搭載されているテンプレートエンジンもそこそこあるんですかね?django以外のテンプレートで継承使ったことある人ってどのくらいいますか? テンプレートはあくまでViewで用意したデータを表現するためのものなので過剰なロジックはかけないようになっています
  52. djangoのtemplateは辞書ライクなオブジェクトを渡してそのデータを使って文字列をレンダリングします 変数の出力は波カッコで変数を囲います。変数と波カッコの間は半角スペースを1つ挟みましょう。
  53. loopなどの制御構文は波カッコパーセントで括ります。forはendforで終わります。 テンプレートでfor文を使うと空っぽの場合と場合分けをしたことがあったりしますので、便利なemptyタグが用意されています。() 他にも暗黙で定義されるループカウンターや最初の一回、最後の一回にTrueとなるフラグなどもあります
  54. ifもendifで終わります これも波カッコパーセントです 初期の頃はこの条件式なんかもほとんど書けなかったんですが、さすがに辛いことが多かったので随分妥協された感じです
  55. forやifもタグなのですが、その他にも色々なタグがあります。 ループで前回のループまでと値が変わった時にTrueになるifchangedなどや、テーブルの色をシマシマにしたい場合に役に立つこのcycleというタグなどは便利でしょう。 テンプレートで少し複雑なことをしたい場合にはカスタムでタグを作ることもあります
  56. filterは変数の出力を整形するものです。 例えばこのlinebreaksbrは変数の改行をHTMLのbrタグに変換するフィルターです filterも標準で色々あるほか、自分で定義して使えます
  57. テンプレートの一番特徴的な部分である継承について少しみていきましょう。 base.htmlというテンプレートがあるとします。 blockとendblockというテンプレートタグで囲まれた部分が幾つかありますよね。() まずはblock titleに注目しましょう。このbase.htmlを継承しているapp/base.htmlというテンプレートがあります。() こっちのテンプレートにもblock titleがありますね。上のbase.htmlを使った場合にはプロジェクト名コロンという文字列が出力されます。app/base.htmlを使った場合には、block.superという親の結果を出力する変数を使っているので、プロジェクト名コロン アプリ名とか という文字列が出力されます。() 同様に、base.htmlのblock contentをapp/some.htmlのblock contentが上書きをしています。 ヘッダーやフッッター、サイドバーなどを指定するレイアウトテンプレートは、継承関係にあるにもかかわらずコンポジットで表すオブジェクト指向みたいな冗長さになるので、djangoではテンプレートでも継承を用います。Djangoにもincludeはありますので、レイアウトテンプレートっぽく使うのもできますが、includeのそういう使い方は見かけたことがありません。(46:30)
  58. viewはもともと関数で、requestを受け取ってresponseを返すという決まりのものでした 今はdjangoに付属しているviewはクラスベースと呼ばれるものが主流になっています。まだ関数ベースのものもあります。 関数をdecoratorでどんどんラップしていっても良いのですが、Pythonは多重継承ができるためmixin的なクラスをいくつも使うようになってきています
  59. - djangoのURLとViewのマッチングファイルはurlpatternsというモジュール変数にurlというもののリストを定義したものです。
  60. 例えばこういうURLが来た場合には、urlpatternsを順番に見ていって、最初に正規表現にマッチしたこの行が使われます。 view関数はviews.month_archive、関数ベースのview関数は第一引数にrequestが渡されることになっていて、正規表現でキャプチャーした値が第二引数以降に渡されて来ます
  61. 名前付きでURLから値をキャプチャすればview関数でもキーワードアーギュメンツで受け取れます
  62. 関数ベースのViewの例を見て見ましょう このシンプルなView関数はrequestを受け取って、HttpResponseを返します。この例ではテンプレートエンジンも使わずに文字列をHttpResponseに渡して返しています。 先ほどのURLconfの例で見たように、URLからキャプチャした引数が関数に渡って来たり、requestオブジェクトにはgetパラメーターやpostデータが格納されてくるので、必要な値を取り出して、必要に応じてモデルやマネージャーを通じてデータベースへアクセスをして、テンプレートエンジンを使ったりしてResponseを返す、これが基本形です。
  63. classベースのViewもシンプルなものは大差ありません。django.views.generic.base.Viewクラスを継承して、dispatchメソッドを定義します あとはrequest引数と、URLconfでキャプチャーした引数が渡されてくるのは関数ベースと同じです
  64. URLconfではクラスベースのViewをCallableにするためのas_viewというクラスメソッドを呼び出して登録します もともとViewは関数だったので、関数ベースのViewとクラスベースのView、どちらも同じ様に扱えるようにクラスベースのViewはCallableに変換するクラスメソッドを呼んでるんです。
  65. Classベースのビューは、dispatchというメソッドのほか、HTTPメソッドに応じたメソッド名で定義をするとHTTPメソッドに応じてクラスベースビューのメソッドが呼び出されるようになっています。(50:00)
  66. 関数ベースのビューのidiomです Import 文は気にせずに、View関数を見ていきます 引数のrequestは大事で、どのHttpMethodで呼び出されたかがmethodという変数に格納されているので、POSTで呼び出されたかを確認しています。 POSTでない場合、elseの方のブロックではformを生成してテンプレートに入力フォームを表示します postの場合にはrequestに格納されているPOSTデータが正しいかをformで検証して、正しい場合には何かしらの操作をしてリダイレクトします PRGパターンですね、Post Redirect Get POSTデータが正しくない場合には正しくないという状態を保ったformを使ってテンプレートに入力フォームを再表示します
  67. クラスベースも基本は同じです getの場合はgetメソッドでformを生成して入力フォームを表示します postの場合はPOSTデータが正しいかをformで検証して、正しい場合には何かしらの操作をしてリダイレクトします POSTデータが正しくない場合には正しくないという状態を保ったformを使ってテンプレートに入力フォームを再表示します 書き方が微妙に違いますが、やることは同じです。postとgetでメソッドが別れた分少し見やすいかもしれませんね (52:00)
  68. Idiom、いつも似たものを書くことになりますので、Djangoの設計思想から外れてしまいます djangoはこんなIdiomでさえもコードの重複とみなしてGeneric ViewというよくあるパターンのViewを用意しています
  69. テンプレートをレンダリングしたいだけの場合には、TemplateをロードしてレンダリングしたものをResponseで返すわけですが、ここで変わってくるのはtemplateのファイルだけだったりします。() 究極的にはViewの定義さえも不要で、URLconfでtemplate名を指定して終わりにできます templateに別のデータを渡したい場合にはURLconfだけではなくて、TemplateViewを継承することになりますが、その場合でもget_context_dataというメソッドを上書きすれば良いように便利なベースクラスになっています
  70. DetailViewはpkをURLから受け取って1つのデータを表示するGeneric View ListViewはリストのデータを抽出して表示するGeneric Viewです それぞれ、利用するモデルから規約でテンプレート名が決まるようになっています TemplateViewのように、追加で表示したいものがある場合には特定のメソッドを上書きすれば良いようになっています
  71. 更新系のGeneric Viewも考え方は同じです 究極的にはモデルと対象のフィールドを指定して、あとは規約で決まった名前でテンプレートを用意するだけです 機能を追加したい場合には、Mixinクラスを用意して多重継承をします
  72. 急にMTV以外のものが出てきました 思想にも登場したルースカップリングにとって重要なものです
  73. 例えば何かのモデルが保存された後に何か処理をしたい場合には、djangoがmodelのsave後に発行しているsignalを使えば良いです 他にもViewの処理が終わった時のSignalなどいろいろなSignalを発行しています この例では、MyModelというモデルのpost_saveというSignalが発行された場合に、my_handlerという関数が実行される様にしています このSignalを受けるという方法にすれば、例えばこのMyModelが含まれているアプリケーションと別のアプリケーションでデータの変更を検知して何かの処理を追加するといったことが可能になります(55:00)
  74. 独自のSignalも簡単に定義できます この例ではdjango.dispatch.Signalに受け取る引数を定義してpizza_doneというsignalを定義しています
  75. 定義したSignalのsendメソッドにsenderとして呼び出し元を渡し、Signalに受け取る引数として定義した引数を渡してSignalを発行します 先ほどのpost_saveと同様に、pizza_doneのreceiverとして登録してある関数が呼ばれます。(56:00)
  76. ここが本日に本題です! djangoの肝は アプリケーションの分割とメンテナンス性の確保 それからPythonに大量のライブラリーがあるように、Djangoには大量の再利用可能なアプリケーションがあるというところです 現代のプログラミングは多くのライブラリーを組み合わせて問題を解決していきます Webアプリケーションも多くの再利用可能なアプリケーションを組み合わせて手数を減らせたら素敵じゃないですか
  77. そもそもサンプルとしてプロジェクトとアプリケーションを作りましたが
  78. プロジェクトには設定ファイルと、URLconfが格納されています settings.pyには利用するアプリケーションを指定するINSTALLED_APPSという設定がありましたよね ここまでのサンプルではurls.pyにはURLとアプリケーションのViewの対応を書きました() 実際はプロジェクトに格納されているurls.pyにはアプリケーションが持っているurls.pyへ移譲する設定を書けば良いです この例の場合には、community/で始まるURLが来た場合には、app_aのurlsにcommunity/が剥ぎ取られたpathが渡されてマッチングが続けられます つまり、アプリケーションのURLはプロジェクトの設定でマウントするURLのPathを制御できます(57:30)
  79. アプリケーションは、ModelとTemplateとViewを持っていることが多いです
  80. 最初は用意されていませんが、標準の設定ではアプリケーションのフォルダ内にtemplatesというフォルダがあるとtemplateの検索パスに加えられます デフォルトのテンプレートをアプリケーションのtemplatesフォルダに用意しましょう 利用者はそのうちの一部をプロジェクトで上書きしたいかもしれません templateの検索パスの先頭にプロジェクトで用意したテンプレート用のディレクトリを指定すると、djangoがtemplateを探す時に先に見つけちゃうので上書きちゃうんですよ!(58:20)
  81. URLconfのurlにはURLの逆引きに使うためのnameが指定できます。というか指定します。 そしてurls.pyモジュールにapp_nameを設定すると urlを逆引きする時にネームスペースを指定できて、nameが他のアプリケーションと重複する可能性が減ります
  82. djangoの認証システムを使う場合には、直接ユーザーのモデルを指定せずにユーザーのモデルクラスを取得する関数を使いましょう djangoの認証システムはバックエンドやユーザーモデルを差し替えられるようになっています。カップリングしてしまっているアプリケーションは多くの場合再利用できなくなってしまうので、これ注意点です。
  83. djangoにデフォルト設定が記載されているglobal_settings.pyを見ておきましょう いろいろな機能が差し替えられるようになっています (1:00:00)
  84. 本丸がささっと終わってしまったんですが、この先見ていくと良さそうなものをいくつか紹介します。
  85. djangoのドキュメントは、Referenceだけでなく、なぜそうしているのかという理由も書かれていますし、評判が良いです 右下の言語のところから日本語に切り替えもできます。() 日本語は国際化ファイルやドキュメントの翻訳カバー率が高い方で大抵は100%になってると思います。django-ja、頑張ってます。
  86. オープンソースなんで、なんだかんだでコードを読むと良いです。 昔に比べると随分サイズが大きくなりましたけど、コメントもしっかり書かれてますし、テストコードもあるので読みやすいと思います djangoはコントリビュートする時に、need patch, need test, need documentというフラグを立てられることがあります コードを取り込んでもらうには、テストとドキュメントを揃えないといけなんです フレームワークなのでMetaプログラミングを活用していたり、django自身がreusable appsを内包していたりもするのでまぁ読むと良いと思います
  87. マルチユーザー・マルチアカウントのエラートラッキングサービスにsentry.ioという商用サービスがあります 実はなんと、() 商用サービスのコードがgithub上で普通に開発が繰り広げられているので参考になるかもしれません
  88. いろんなサイトの開発してると、やっぱり似たようなコードを何度も書いてるよねーと思った人が始めたreuseble appsたくさん組み合わせてこーぜ、というプロジェクトですかね() github見ると、77リポジトリってなってます ユーザーアカウント系やらノーティフィケーション系みたいなものだけじゃなくって決済系も再利用可能なアプリとして公開されていて、多くのものは相互に依存もしていなそうなので使えるものがあるかもしれません。
  89. djangoのアプリを集めてるサイトです() アプリカテゴリには2880って数が出てますね(2017/11/08) このサイトをメンテしてる夫婦が書いている本がなかなか良くて、評判良いです() ちょっとお高いですけど、すでに1.11対応版が出てます。1.5くらいのやつを買ってたんですけど、今回1.11のやつも買いました()
  90. PDFじゃなくってkindleとか紙とかで良い人はこのURLを踏んでもらうと潤います! あ、ちなみにまだ英語の本です() (1秒ご、)随分早いな、と思ってるでしょうけど、何か質問ありますか?