PyLadies Remote

By Emmanuelle Delescolle - @EmmaDelescolle

Django Introduction

Starting at 2.45pm cet

But before we get started...

  • Register a free account on
  • Create a new CUSTOM workspace
  • Initialize your workpace by typing the following in a terminal (<alt><T>)

  • Follow the instructions (most defaults should be correct)
  • Create a default runner (Run -> Run Configurations -> Manage...)
    • Command:../venv_django_todo/bin/python runserver $ip:$port
    • PWD:/django_todo
    • Name:Runserver
sudo pip install cookiecutter
cookiecutter bb:emma_nuelle/cc_plr_django_intro

What did you just do?

A different approach

We will focus on steps between 1 and 2 only Django and a little bit of HTML

Image found on Know your Meme


Unlike with PHP or static HTML, the web server will not try to find script files according to the requested URL. URL's are passed "as is" to Django who will take care of parsing them.

Parsing of URL's happens according to <project_dir>/ A bit like in the router of RoR (without resources).

url(r'^$', TemplateView.as_view(template_name='base.html'), name='home'),

If you'd like to know more about what REGEXes are, you may want to check out the official Python documentation.

Hello world

Let's see what happens if we replace base.html with another template.

Django looks for templates in every INSTALLED_APP's templates directory.

Django models

Models are entities that you would like to persist (or save).

Models have properties called fields.
In the case of a ToDo item, we have 2 properties:

Models are defined in <app_name>/
In order for Django to be aware of your models the application <app_name> has to be listed in INSTALLED_APPS in your file

Database migrations?

Django Models are actually stored in a database.
In order for your project to work properly, the Models you define in your files also have to be defined in the database.
For that to happen, every time you change something in a file, you have to ask Django to create a migration and then you'll have to apply it.

Migration files are just files with a set of instructions only a database engine can understand.


In order to create a migration, go to the terminal window (with your virtualenv activated) and run the following command:

Now, we have to apply the migration by running:

./ makemigations
./ migrate

Django Admin

In order for you to easily add/edit/delete items (model instances), Django provides an easy to use admin.

To make your newly model available in the admin, all you have to do is register it.

I want more!

In order to make the ModelAdmin more user friendly, Django offers plenty of options so that you can customize each and every admin page to your needs.
Let's try a couple of those!

More templates
Less work

A template can be the exact copy of another template and only override portions (blocks) of it. It's called template inheritance.

Views - The logic of your application

The logic of your application in Django is placed in a file called (inside the application directory).

Since the logic behind a lot of web pages is often the same (list all items from a model, create/ edit/ delete one of those items) Django provides a set of Generic Class-Based Views which are nicely documented on

GCBV's are like lasagnas

(in a good way) - We love lasagna!

Garfieldยฉ is copyrighted but I found another kitten to sacrifice on a decent subreddit. Also checkout this one

I don't like beef lasagnas ๐Ÿ˜ž

Don't worry, with those lasagnas, you can pick away any layer you don't like and replace it with one better suited to your liking!

Let's see it in action by creating our first ListView!

10 minutes break

Let's make our toolbox BIGGER!

๐Ÿ”ง ๐Ÿ”จ ๐Ÿ”ฉ

pip install django-debug-toolbar

Contextual (help)

In Django views, a context is a dictionary of values that the view passes to the template.

Are we done yet?

In a Class-Based View, you can easily add information to the context by overridding get_context_data.

Let's add the number of ToDo's left in the footer

Build on top of your lasagna

As with templates, you can create new views on top of other views and only override the parts that change.

Photo by Hannah Whitaker, found on

Let's build filtered views with some custom Querysets.

Looks like we found a bug...

Let's take a closer look!

Illustration by Persian Poet Gal

What? Why? How?

     def get_context_data(self, **kwargs):
         context = super(ToDoListView, self).get_context_data(**kwargs)
         context['todos_left'] = self.get_queryset().filter(done=False).count()
         context['active_menu'] = self.active_menu
         return context
     def get_queryset(self):
         qs = super(DoneToDoListView, self).get_queryset()
         return qs.filter(done=True)


Let's fix that by using a different Queryset

10 minutes break

Lasagnas are like cards

Lasagnas are like cards, you can shuffle them!
(Please don't try this at home with real lasagnas)

2 cheesy crusts?

The problem when shuffling 2 lasagnas together is that both lasagnas have a melted cheese top layer.
It would be much easier to shuffle a full lasagna with a lasagna stub!

When it comes to Class-Based Views, Django provides lasagna stubs which are called mixins.

Been there, Done that

When clicking on a ToDo's checkbox, we want Django to update the ToDo and then redirect us back to the homepage.

To do that, we will shuffle a SingleObjectMixin which will provide us with the ToDo we need to update, with a RedirectView which will send us back to the homepage.

Return of the REGEX

in order for our View to know which ToDo it needs to fetch, we have to give it a clue, that clue is called a pk.

url(r'^toggle/(?P<pk>\d+)/$', ToggleDoneView.as_view(), name='toggle'),

All you really need to remember from this is that the bizarre string (?P<pk>\d+) is how you tell Django that the URL will contain a pk.

It's easier to write on the template side:

{% url 'toggle' %}

Ready for dessert?

CreateView's don't have a mixin equivalent but ListView's do, it's called MultipleObjectMixin.

It will only take an extra few lines of code to allow us to create more ToDo's (haven't we done enough yet?)

Pretty nom nom

๐ŸŽ‰ Congratulations! ๐ŸŽ‰

To much on my plate!

To delete a ToDo, the logic is almost the same as to toggle one.

Let's stay DRY, nobody likes wet lasagna anyways!


Let's introduce the magic with (m)AJAX and Django's is_ajax()

Yet another flavour of lasagna

Let's tie it all up together and add the ability to update a ToDo item with an UpdateView.

Almost there!

The only thing left to do now is to enable AJAX for ToDo items creation!

๐ŸŽ‰ All Done! ๐ŸŽ‰

Made with