2. Who am I?
● Started using Python 1.5.2 in 1998
● Started using Django 0.96 in 2008
● Contributing to open source projects since ~2000
● @mrbeersnob
● github.com/tarkatronic
4. No, really, what is it?
The web framework for professionals with deadlines
● Originally built for the Lawrence Journal-World newspaper in 2003
● A bundled collection of tools to build powerful web applications quickly
● Focused on automation and DRY
5. Who actually uses this thing?
● Disqus
● Instagram
● Pinterest
● Washington Post
● National Geographic
● Many, many more…
● https://www.djangosites.org/
6. Why should I use it?
● ORM
● Caching
● Internationalization
● Class-based views!
● Templating
● Automatically generated admin interface
● Database migrations
● Built-in management commands
7. Django doesn’t provide ____. Do I have to build it?
● Social authentication? django-allauth
● REST API? django-rest-framework
● Two factor authentication? django-two-factor-auth
● CMS? wagtail, django-cms, etc
● https://www.djangopackages.com/
● https://djangosnippets.org/
13. A couple more...
class Drink(models.Model):
name = models.CharField(max_length=255)
components = models.ManyToManyField('Ingredient', through='Component', related_name='drinks')
def __str__(self):
return self.name
class Component(models.Model):
drink = models.ForeignKey('recipes.Drink', related_name='+')
ingredient = models.ForeignKey('recipes.Ingredient', related_name='+')
amount = models.FloatField()
def __str__(self):
return '%s %s %s (%s)' % (self.ingredient.name, self.amount,
self.ingredient.get_measurement_display() or '', self.drink.name)
14. One more piece
class Step(models.Model):
drink = models.ForeignKey('Drink', related_name='steps')
text = models.TextField()
class Meta:
order_with_respect_to = 'drink'
def __str__(self):
return '%s step #%s' % (self.drink.name, self._order + 1)
15. Time to set up the database...
CREATE DATABASE;
CREATE TABLE …;
...right?
16. Nope! Migrations to the rescue.
./manage.py makemigrations
Migrations for 'recipes':
0001_initial.py:
- Create model Component
- Create model Drink
- Create model Ingredient
- Create model Step
- Add field components to drink
- Add field drink to component
- Add field ingredient to component
- Set order_with_respect_to on step to drink
./manage.py migrate
Operations to perform:
Synchronize unmigrated apps: staticfiles, messages
Apply all migrations: admin, contenttypes, recipes, auth, sessions
… lots more words …
Done!
17. About that admin interface...
admin.py:
from django.contrib import admin
from .models import Component, Drink, Ingredient, Step
class ComponentInline(admin.TabularInline):
model = Component
class StepInline(admin.StackedInline):
model = Step
class DrinkAdmin(admin.ModelAdmin):
inlines = [ComponentInline, StepInline]
admin.site.register(Component)
admin.site.register(Drink)
admin.site.register(Ingredient)
admin.site.register(Step)
18. Creating an admin user
Another built-in management command!
./manage.py createsuperuser
Username (leave blank to use 'jwilhelm'):
Email address: jwilhelm@opay.io
Password:
Password (again):
Superuser created successfully.
22. Making things visible: views
views.py:
from django.core.urlresolvers import reverse_lazy
from django.views.generic import DetailView, ListView
from .models import Component, Drink
class DrinkListView(ListView):
model = Drink
class DrinkDetailView(DetailView):
model = Drink
def get_context_data(self, **kwargs):
context = super(DrinkDetailView, self).get_context_data(**kwargs)
context.update({'components': Component.objects.filter(drink=self.get_object())})
return context
23. Pulling it together with a couple templates
base.html:
<html>
<head>
<title>Cocktail Database</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
24. List all the things!
recipes/drink_list.html:
{% extends "base.html" %}
{% block content %}
{% for drink in object_list %}
{% if forloop.first %}
<ul>
{% endif %}
<li><a href="{% url 'drink_detail' drink.id %}">{{ drink.name }}</a></li>
{% if forloop.last %}
</ul>
{% endif %}
{% empty %}
No drinks yet in the database.
{% endfor %}
{% endblock %}
25. It's all in the details
recipes/drink_detail.html:
{% extends "base.html" %}
{% block content %}
<h1>{{ drink.name }}</h1>
<dl>
<dt>Ingredients</dt>
<dd>
<ul>
{% for component in components %}
<li>{{ component.amount }}{% if component.ingredient.measurement %} {{
component.ingredient.measurement }}{% endif %} {{ component.ingredient.name }}</li>
{% endfor %}
</ul>
</dd>
...
30. The full code, plus a bit more
django-cocktails repository: https://github.com/tarkatronic/django-cocktails
31. What if I need help?
“I came for the auto generated admin, but I stayed for the community.”
-Ola Sitarska
● StackOverflow - http://stackoverflow.com/questions/tagged/django
● django-users mailing list - https://groups.google.com/forum/#!forum/django-
users
● IRC: #django on Freenode (I'm often on as TheJoey)
32. Now, go learn more!
Django Project website: http://www.djangoproject.com/
Django Girls tutorial: http://tutorial.djangogirls.org/
Getting Started with Django: http://gettingstartedwithdjango.com/
Two Scoops of Django: http://twoscoopspress.org/