Django - A Whirlwind Tour 2016

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.

D57aec10399cbb252bd890c2bb3fe1c9?s=128

Brad Montgomery

October 14, 2016
Tweet

Transcript

  1. 2.

    Who is this guy? • Working with Python + Django

    since 2009 • Tech Lead at Tennessee Data Commons (501c3) • MEMpy Organizer • “full-stack” web developer.
  2. 3.

    Django: Features • MVC-inspired (MVT) • Security. • A large

    community / Lots of open source • Worlds Best Documentation • The web framework for perfectionists with deadlines.
  3. 4.

    Django: Neat Facts • Since 2005 • 1200+ Contributors •

    django.tar.gz ~ 8Mb • 94% python • 261,776 lines of code (w/ comments)
  4. 5.

    Batteries Included • ORM • Django Template Language • Testing

    Framework (unittest) • Contrib apps: • Commonly needed things bundled with Django. • Admin, Syndication, Flash messages, GIS
  5. 9.

    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)
  6. 13.

    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
  7. 15.

    Projects & Apps foo/ ├── manage.py └── foo/ ├── __init__.py

    ├── settings.py ├── urls.py └── wsgi.py Project directory
  8. 16.

    Projects & Apps foo/ ├── manage.py └── foo/ ├── __init__.py

    ├── settings.py ├── urls.py └── wsgi.py Project- specific CLI
  9. 17.

    Projects & Apps foo/ ├── manage.py └── foo/ ├── __init__.py

    ├── settings.py ├── urls.py └── wsgi.py Project settings, etc
  10. 22.

    Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py App directory
  11. 23.

    Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py (special python file)
  12. 24.

    Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Admin Config
  13. 25.

    Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py App Config
  14. 26.

    Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Database Migrations
  15. 27.

    Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Data Models
  16. 28.

    Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py (Unit) Tests
  17. 29.

    Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Http Request handlers. (Controllers)
  18. 30.

    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
  19. 31.

    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
  20. 32.

    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
  21. 33.

    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
  22. 34.

    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
  23. 35.

    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
  24. 36.

    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
  25. 37.

    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
  26. 38.

    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
  27. 39.

    A base template <!DOCTYPE html> <html> <head> <title> {% block

    title %}{% endblock %} </title> </head> <body> {% block content %}{% endblock %} </body> </html> blog/templates/blog/base.html
  28. 40.

    A base template <!DOCTYPE html> <html> <head> <title> {% block

    title %}{% endblock %} </title> </head> <body> {% block content %}{% endblock %} </body> </html> blog/templates/blog/base.html
  29. 41.

    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
  30. 42.

    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
  31. 43.

    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
  32. 44.

    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
  33. 45.

    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
  34. 46.

    URL Conf’s • Tie it all together! • Route HTTP

    requests to views (functions) • May also capture values using Regex
  35. 47.

    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.
  36. 48.

    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.
  37. 49.

    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.
  38. 50.

    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
  39. 51.

    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.
  40. 52.

    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
  41. 53.

    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
  42. 54.

    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/
  43. 55.

    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
  44. 56.

    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
  45. 62.

    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/
  46. 63.

    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/
  47. 64.

    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
  48. 65.

    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
  49. 66.

    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...
  50. 67.

    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
  51. 71.

    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
  52. 72.

    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
  53. 73.

    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
  54. 74.

    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
  55. 75.

    Model Forms… from django.forms.models import ModelForm from .models import Post

    class PostForm(ModelForm): class Meta: model = Post fields = ('title', 'content' )
  56. 77.

    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…
  57. 84.
  58. 85.

    A Typical Stack PostgreSQL Gunicorn + Django Gunicorn + Django

    nginx PostgreSQL writes reads repl. Redis Memcached RabbitMQ Varnish
  59. 86.
  60. 87.

    Heroku. Easy. • Deploy & Scale in the Cloud •

    Sign up at heroku.com • Get the Heroku CLI • Deploying Python and Django Apps on Heroku
  61. 89.

    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
  62. 92.