Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Brad Montgomery

October 14, 2016
Tweet

More Decks by Brad Montgomery

Other Decks in Programming

Transcript

  1. Who is this guy? • Working with Python + Django

    since 2009 • Tech Lead at Tennessee Data Commons (501c3) • MEMpy Organizer • “full-stack” web developer.
  2. Django: Features • MVC-inspired (MVT) • Security. • A large

    community / Lots of open source • Worlds Best Documentation • The web framework for perfectionists with deadlines.
  3. Django: Neat Facts • Since 2005 • 1200+ Contributors •

    django.tar.gz ~ 8Mb • 94% python • 261,776 lines of code (w/ comments)
  4. Batteries Included • ORM • Django Template Language • Testing

    Framework (unittest) • Contrib apps: • Commonly needed things bundled with Django. • Admin, Syndication, Flash messages, GIS
  5. 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. 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. Projects & Apps foo/ ├── manage.py └── foo/ ├── __init__.py

    ├── settings.py ├── urls.py └── wsgi.py Project directory
  8. Projects & Apps foo/ ├── manage.py └── foo/ ├── __init__.py

    ├── settings.py ├── urls.py └── wsgi.py Project- specific CLI
  9. Projects & Apps foo/ ├── manage.py └── foo/ ├── __init__.py

    ├── settings.py ├── urls.py └── wsgi.py Project settings, etc
  10. Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py App directory
  11. Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py (special python file)
  12. Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Admin Config
  13. Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py App Config
  14. Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Database Migrations
  15. Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Data Models
  16. Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py (Unit) Tests
  17. Projects & Apps foo/ ├── blog ├── __init__.py ├── admin.py

    ├── apps.py ├── migrations/ ├── models.py ├── tests.py └── views.py Http Request handlers. (Controllers)
  18. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. URL Conf’s • Tie it all together! • Route HTTP

    requests to views (functions) • May also capture values using Regex
  35. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Model Forms… from django.forms.models import ModelForm from .models import Post

    class PostForm(ModelForm): class Meta: model = Post fields = ('title', 'content' )
  56. 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. A Typical Stack PostgreSQL Gunicorn + Django Gunicorn + Django

    nginx PostgreSQL writes reads repl. Redis Memcached RabbitMQ Varnish
  58. Heroku. Easy. • Deploy & Scale in the Cloud •

    Sign up at heroku.com • Get the Heroku CLI • Deploying Python and Django Apps on Heroku
  59. 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