Share
Embed
Django - A Whirlwind Tour 2016
Slides for my talk given at DevSpace Conf 2016 -- Django is a leading web development framework written in Python, and has long been billed as "the web framework for perfectionists with deadlines".
This talk will quickly walk you through a typical django project, illustrating some of django's "batteries included" features and some common conventions used in many apps.
Brad Montgomery
October 14, 2016
Transcript
92 slides
-
Who is this guy? • Working with Python + Django
since 2009 • Tech Lead at Tennessee Data Commons (501c3) • MEMpy Organizer • “full-stack” web developer. -
Django: Features • MVC-inspired (MVT) • Security. • A large
community / Lots of open source • Worlds Best Documentation • The web framework for perfectionists with deadlines. -
Django: Neat Facts • Since 2005 • 1200+ Contributors •
django.tar.gz ~ 8Mb • 94% python • 261,776 lines of code (w/ comments) -
Batteries Included • ORM • Django Template Language • Testing
Framework (unittest) • Contrib apps: • Commonly needed things bundled with Django. • Admin, Syndication, Flash messages, GIS -
Community • The Python Community • Meetups / Conferences (DjangoCon)
• 3rd-party, open source apps • django-registration (signup, account reset) • django-taggit (Tagging content) • django-storages (File storage on S3) • django-crispy-forms (Form layout tools) • Django REST Framework (restful apis) -
Projects & Apps • Projects are a collection of Django
apps. • MDN: https://developer.mozilla.org/ • API that powers a mobile app (app.tndata.org) • Settings, DB, Apps, Filesystem info. • Command-line tool: manage.py -
Projects & Apps foo/ ├── manage.py └── foo/ ├── __init__.py
├── settings.py ├── urls.py └── wsgi.py Project directory -
Projects & Apps foo/ ├── manage.py └── foo/ ├── __init__.py
├── settings.py ├── urls.py └── wsgi.py Project- specific CLI -
Projects & Apps foo/ ├── manage.py └── foo/ ├── __init__.py
├── settings.py ├── urls.py └── wsgi.py Project settings, etc -
Projects & Apps $ python manage.py runserver Dev server running
at: 127.0.0.1:8000 -
Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py
├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py App directory -
Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py
├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py (special python file) -
Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py
├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Admin Config -
Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py
├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py App Config -
Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py
├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Database Migrations -
Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py
├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Data Models -
Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py
├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py (Unit) Tests -
Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py
├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Http Request handlers. (Controllers) -
Models from django.db import models from django.contrib.auth.models import User class
Post(models.Model): author = models.ForeignKey(User) title = models.CharField(max_length=128) slug = models.SlugField(max_length=128, unique=True) content = models.TextField() published_on = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['published_on', ] verbose_name = "Post" verbose_name_plural = "Posts" foo/blog/models.py -
Models from django.db import models from django.contrib.auth.models import User class
Post(models.Model): author = models.ForeignKey(User) title = models.CharField(max_length=128) slug = models.SlugField(max_length=128, unique=True) content = models.TextField() published_on = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['published_on', ] verbose_name = "Post" verbose_name_plural = "Posts" foo/blog/models.py -
Models from django.db import models from django.contrib.auth.models import User class
Post(models.Model): author = models.ForeignKey(User) title = models.CharField(max_length=128) slug = models.SlugField(max_length=128, unique=True) content = models.TextField() published_on = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['published_on', ] verbose_name = "Post" verbose_name_plural = "Posts" foo/blog/models.py -
Models from django.db import models from django.contrib.auth.models import User class
Post(models.Model): author = models.ForeignKey(User) title = models.CharField(max_length=128) slug = models.SlugField(max_length=128, unique=True) content = models.TextField() published_on = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['published_on', ] verbose_name = "Post" verbose_name_plural = "Posts" foo/blog/models.py -
Models from django.db import models from django.contrib.auth.models import User class
Post(models.Model): author = models.ForeignKey(User) title = models.CharField(max_length=128) slug = models.SlugField(max_length=128, unique=True) content = models.TextField() published_on = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['published_on', ] verbose_name = "Post" verbose_name_plural = "Posts" foo/blog/models.py -
Views from django.shortcuts import render from .models import Post def
list_posts(request): context = { 'posts': Post.objects.all(), } template = "blog/list.html" return render(request, template, context) foo/blog/views.py -
Views from django.shortcuts import render from .models import Post def
list_posts(request): context = { 'posts': Post.objects.all(), } template = "blog/list.html" return render(request, template, context) foo/blog/views.py -
Views from django.shortcuts import render from .models import Post def
list_posts(request): context = { 'posts': Post.objects.all(), } template = "blog/list.html" return render(request, template, context) foo/blog/views.py -
Views from django.shortcuts import render from .models import Post def
list_posts(request): context = { 'posts': Post.objects.all(), } template = "blog/list.html" return render(request, template, context) foo/blog/views.py -
A base template <!DOCTYPE html> <html> <head> <title> {% block
title %}{% endblock %} </title> </head> <body> {% block content %}{% endblock %} </body> </html> blog/templates/blog/base.html -
A base template <!DOCTYPE html> <html> <head> <title> {% block
title %}{% endblock %} </title> </head> <body> {% block content %}{% endblock %} </body> </html> blog/templates/blog/base.html -
A list template {% extends "blog/base.html" %} {% block title
%} Posts {% endblock %} {% block content %} <h1>Posts</h1> <ul> {% for post in posts %} <li> <a href="{{ post.get_absolute_url }}">{{ post.title }}</a> posted {{ post.published_on|timesince }} ago. </li> {% endfor %} </ul> {% endblock %} blog/templates/blog/list.html -
A list template {% extends "blog/base.html" %} {% block title
%} Posts {% endblock %} {% block content %} <h1>Posts</h1> <ul> {% for post in posts %} <li> <a href="{{ post.get_absolute_url }}">{{ post.title }}</a> posted {{ post.published_on|timesince }} ago. </li> {% endfor %} </ul> {% endblock %} blog/templates/blog/list.html -
A list template {% extends "blog/base.html" %} {% block title
%} Posts {% endblock %} {% block content %} <h1>Posts</h1> <ul> {% for post in posts %} <li> <a href="{{ post.get_absolute_url }}">{{ post.title }}</a> posted {{ post.published_on|timesince }} ago. </li> {% endfor %} </ul> {% endblock %} blog/templates/blog/list.html -
A list template {% extends "blog/base.html" %} {% block title
%} Posts {% endblock %} {% block content %} <h1>Posts</h1> <ul> {% for post in posts %} <li> <a href="{{ post.get_absolute_url }}">{{ post.title }}</a> posted {{ post.published_on|timesince }} ago. </li> {% endfor %} </ul> {% endblock %} blog/templates/blog/list.html -
A list template {% extends "blog/base.html" %} {% block title
%} Posts {% endblock %} {% block content %} <h1>Posts</h1> <ul> {% for post in posts %} <li> <a href="{{ post.get_absolute_url }}">{{ post.title }}</a> posted {{ post.published_on|timesince }} ago. </li> {% endfor %} </ul> {% endblock %} blog/templates/blog/list.html -
URL Conf’s • Tie it all together! • Route HTTP
requests to views (functions) • May also capture values using Regex -
Root URLConf from django.conf.urls import include, url from django.contrib import
admin urlpatterns = [ url(r’^blog/', include(‘blog.urls’)), url(r'^admin/', include(admin.site.urls)), ] foo/foo/urls.py Part of your project config. -
Root URLConf from django.conf.urls import include, url from django.contrib import
admin urlpatterns = [ url(r’^blog/', include(‘blog.urls’)), url(r'^admin/', include(admin.site.urls)), ] foo/foo/urls.py Part of your project config. -
Root URLConf from django.conf.urls import include, url from django.contrib import
admin urlpatterns = [ url(r’^blog/', include(‘blog.urls’)), url(r'^admin/', include(admin.site.urls)), ] foo/foo/urls.py Part of your project config. -
Root URLConf from django.conf.urls import include, url from django.contrib import
admin urlpatterns = [ url(r’^blog/', include(‘blog.urls’)), url(r'^admin/', include(admin.site.urls)), ] foo/foo/urls.py Part of your project config. example.com/blog/hello-world -
Root URLConf from django.conf.urls import include, url from django.contrib import
admin urlpatterns = [ url(r’^blog/', include(‘blog.urls’)), url(r'^admin/', include(admin.site.urls)), ] foo/foo/urls.py Part of your project config. -
Our app’s URLs from django.conf.urls import url from . import
views urlpatterns = [ url(r'^$', views.list_posts, name='list_posts'), url(r’^(?P<post_slug>.+)/$', views.display_post, name='display_post'), ] foo/blog/urls.py -
Our app’s URLs from django.conf.urls import url from . import
views urlpatterns = [ url(r'^$', views.list_posts, name='list_posts'), url(r’^(?P<post_slug>.+)/$', views.display_post, name='display_post'), ] foo/blog/urls.py -
Our app’s URLs from django.conf.urls import url from . import
views urlpatterns = [ url(r'^$', views.list_posts, name='list_posts'), url(r’^(?P<post_slug>.+)/$', views.display_post, name='display_post'), ] foo/blog/urls.py example.com/blog/ -
Our app’s URLs from django.conf.urls import url from . import
views urlpatterns = [ url(r'^$', views.list_posts, name='list_posts'), url(r’^(?P<post_slug>.+)/$', views.display_post, name='display_post'), ] foo/blog/urls.py -
Our app’s URLs from django.conf.urls import url from . import
views urlpatterns = [ url(r'^$', views.list_posts, name='list_posts'), url(r’^(?P<post_slug>.+)/$', views.display_post, name='display_post'), ] foo/blog/urls.py example.com/blog/hello-world -
“Installing” our app. INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions',
'django.contrib.messages', ‘django.contrib.staticfiles', 'blog', ] foo/foo/settings.py -
An HTTP Request from django.conf.urls import include, url from django.contrib
import admin urlpatterns = [ url(r’^blog/', include(‘blog.urls’)), url(r'^admin/', include(admin.site.urls)), ] foo/foo/urls.py — The Root URLConf blog/sample-title/ -
An HTTP Request urlpatterns = [ url(r'^$', views.list_posts, name='list_posts'), url(r’^(?P<post_slug>.+)/$',
views.display_post, name='display_post'), ] foo/blog/urls.py — App URLConf blog/sample-title/ -
An HTTP Request def display_post(request, post_slug): context = { 'post':
Post.objects.get(slug=post_slug) } template = "blog/post.html" return render(request, template, context) foo/blog/views.py sample-title -
An HTTP Request {% extends "blog/base.html" %} {% block title
%} {{ post.title }} {% endblock %} {% block content %} <h1>{{ post.title }}</h1> {{ post.content|urlize|linebreaks }} <p>Published on: {{ post.published_on|date:"M d, Y" }}</p> {% endblock %} foo/blog/templates/blog/post.html Sample Title -
An HTTP Request {% extends "blog/base.html" %} {% block title
%} {{ post.title }} {% endblock %} {% block content %} <h1>{{ post.title }}</h1> {{ post.content|urlize|linebreaks }} <p>Published on: {{ post.published_on|date:"M d, Y" }}</p> {% endblock %} foo/blog/templates/blog/post.html Lorem Ipsum... -
An HTTP Request {% extends "blog/base.html" %} {% block title
%} {{ post.title }} {% endblock %} {% block content %} <h1>{{ post.title }}</h1> {{ post.content|urlize|linebreaks }} <p>Published on: {{ post.published_on|date:"M d, Y" }}</p> {% endblock %} foo/blog/templates/blog/post.html Oct 14, 2016 -
The Django Admin from django.contrib import admin from .models import
Post @admin.register(Post) class PostAdmin(admin.ModelAdmin): list_display = ( 'title', 'author', ‘published_on' ) prepopulated_fields = {"slug": ("title",)} foo/blog/admin.py -
The Django Admin from django.contrib import admin from .models import
Post @admin.register(Post) class PostAdmin(admin.ModelAdmin): list_display = ( 'title', 'author', ‘published_on' ) prepopulated_fields = {"slug": ("title",)} foo/blog/admin.py -
The Django Admin from django.contrib import admin from .models import
Post @admin.register(Post) class PostAdmin(admin.ModelAdmin): list_display = ( 'title', 'author', ‘published_on' ) prepopulated_fields = {"slug": ("title",)} foo/blog/admin.py -
The Django Admin from django.contrib import admin from .models import
Post @admin.register(Post) class PostAdmin(admin.ModelAdmin): list_display = ( 'title', 'author', ‘published_on' ) prepopulated_fields = {"slug": ("title",)} foo/blog/admin.py -
Model Forms… from django.forms.models import ModelForm from .models import Post
class PostForm(ModelForm): class Meta: model = Post fields = ('title', 'content' ) -
Model Forms… @admin.register(Post) class PostAdmin(admin.ModelAdmin): list_display = ( 'title', 'author',
‘published_on' ) form = PostForm -
Other Tools • Forms: Generate form UI, & sanitize/ validate
user input. • The ORM: Complex Queries, Custom Managers (table-level queries), Aggregates, dropping to raw SQL. • Middleware: Doing stuff on every request • Security, Caching, Logging, custom manage.py commands… -
A Typical Stack PostgreSQL Gunicorn + Django Gunicorn + Django
nginx PostgreSQL writes reads repl. -
A Typical Stack PostgreSQL Gunicorn + Django Gunicorn + Django
nginx PostgreSQL writes reads repl. Redis Memcached RabbitMQ Varnish -
Heroku. Easy. • Deploy & Scale in the Cloud •
Sign up at heroku.com • Get the Heroku CLI • Deploying Python and Django Apps on Heroku -
Deploy to Heroku $ git push heroku master After a
bit of setup… -
Learn More? • Official Django Docs • Hello Web App
by Tracy Osborne • Design and build your own custom web app using Python and Django. Tailored for non- programmers, written by a designer. • Two Scoops of Django by Daniel & Audrey Roy Greenfeld • github.com/bradmontgomery/whirlwind_tour