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

Django 101

Django 101

Tutorial from PyCon 2016. A 30,000ft overview of all of the major areas of Django.

Kenneth Love

May 29, 2016
Tweet

More Decks by Kenneth Love

Other Decks in Programming

Transcript

  1. I teach Python, Django, and other stuff for Treehouse I’m

    writing a book for No Starch Press I’ve been co-organizing Django Girls Portland
  2. So, I can’t do this tutorial alone. Y’all have to

    ask questions every step of the way. Yes, that might mean we don’t get all the way through. That’s OK. Twitter, CodeNewbie, etc
  3. This is going to be a high level overview of

    Django with some sudden dips and turns to keep you on your feet and feeling a bit nauseous
  4. This is gonna be fairly hands-off, though, because code inflates

    time so much. I’ll show examples, though. A lot of the examples will be pseudocode, though. Of course, that means it’ll still look like Python!
  5. Django is a framework for building web apps. It can

    be used for other stuff, too, but this is what it’s best at. Came from the world of newspapers/publishing and that still influences it
  6. The ORM The ORM (object relational mapper) is how Django

    turns Python into database records and vice versa. This includes the “model” or “M” part of MVC
  7. Forms Forms are used to create HTML-based inputs for users

    to use. They’re also use, better IMO, to validate data
  8. Templates Templates combine variables, context processors (we’ll get to them

    later), and text to generate a single output file. Usually this file is HTML but it doesn’t have to be. Templates are called “views” in other frameworks
  9. Views Views are the transition layer between HTTP requests and

    HTTP responses. In most other frameworks, they’re called “controllers”.
  10. Admin And, finally, the admin is a really handy tool

    that Django gives you for doing data entry. It’s pretty full-featured out of the box and can be heavily customized.
  11. Project A project is your whole entire web app or

    site or whatever. It’s all of the Django bits and bobs together in one package.
  12. dieter db.sqlite3 manage.py dieter __init__.py settings.py urls.py wsgi.py When I

    say “project” or “project-wide” or “project-level”, this is the file structure of what I’m talking about. An overarching directory that holds your database (assuming you’re using sqlite3 for development), the stubby fake app where your settings live, and the manage.py file for running commands.
  13. App An app, though, is just one piece of the

    project. An app generally encompasses a single idea in your app. If you’re making a site for diets, meals, exercise, etc would be the apps.
  14. meals __init__.py migrations admin.py apps.py models.py tests.py views.py templates And

    an app’s structure is something like this. All the pieces you need to express a software idea.
  15. Why make a new app? It’s usually all about the

    models Apps are mostly defined by their models. Less is more, most of the time. Your app should have 1 or 2 main models and you generally name the app after the model, pluralized. If your main model is “Meal”, your app would be “meals”. When you find yourself creating a ton of models for an app, that’s a good time to re-evaluate the app and the models and decide if they should be split up. If you find yourself make a model that doesn’t really relate to the other models, you probably need a new app. A lot of this comes with experience, though, and like most things in programming, especially Python and Django, if it feels hard to do, it’s probably not the right solution.
  16. Meal Recipe Ingredient Gym Exercise Let’s pretend that we have

    all of these models in one app. Would it make sense to break them up into two or more apps?
  17. Meal Recipe Ingredient Gym Exercise Sure, probably two apps: one

    that’s about food and another that’s about activity
  18. OK, ready to dive down a little further? You can

    stop me to ask questions at any time and I’ll expect questions when you see this icon.
  19. Models & the ORM So let’s talk about how we

    hold onto data, since that’s what most web apps are all about
  20. Models Models are classes that relate, pretty closely, to database

    tables. They have fields that represent the columns in a table and each record is a row in the table
  21. Queries Queries manipulate data. They create new records, update, or

    delete existing records. They also let you filter and find records.
  22. Exercise.objects.create( name=“Light walk”, description=“A stroll around the neighborhood” duration=30, difficulty=1,

    intensity=1 ) Here I’m creating an Exercise. Once Django evaluates this, there’ll be a new record in the database.
  23. Recipe.objects.filter( ingredients__ingredient__name__icontains=‘spinach’, cook_time__lte=60, prep_time__lte=15 ) And here I’m looking for

    a recipe that includes spinach, takes an hour or less to cook, and can be prepped in 15 minutes or less.
  24. Did you notice the .objects? That’s a model manager and

    it controls what actions are available on a model. The default one has things like filter, delete, etc. You can make your own if you want to have special actions for your models Querysets?
  25. OK, ready to dive down a little further? You can

    stop me to ask questions at any time and I’ll expect questions when you see this icon.
  26. Inheritance Sometimes your models have a lot in common. So

    much so, in fact, that it doesn’t make sense to repeat all of those fields. Django has two types of inheritance.
  27. Multi-table Multiple table inheritance, or MTI, creates multiple tables. You

    might have guessed that from the name. MTI creates a table for every model and automatically creates a relationship between the child models and the parent model. Here’s an example:
  28. Message: created_at created_by content Email(Message): to_address SMS(Message): to_number This would

    create three database tables, one for each model. But if you had an Email record selected, you could go through the “message” OneToOne field to get to the created_at, created_by, and content fields.
  29. Abstract Abstract inheritance doesn’t create new database tables. Child models

    get all of the fields of the parent models, though. Here’s an example that might be familiar
  30. Message: created_at created_by content class Meta: abstract = True Email(Message):

    to_address SMS(Message): to_number This will only create two tables. Both the Email and SMS tables will have their own created_at, created_by, and content columns.
  31. OK, ready to dive down a little further? You can

    stop me to ask questions at any time and I’ll expect questions when you see this icon.
  32. Relationships Did you notice the ForeignKey fields in some of

    the example models? And I mentioned a “message” OneToOne” field for MTI inheritance? Django models have a few really useful ways to connect records together.
  33. Foreign Key The most common is the foreign key relationship.

    Depending on which side of it you’re on, it can also be called a “one to many” or “many to one” relationship. If you had a Star instance, it could have many Planet instances related to it. A Planet instance, though, would only have one Star it was related to. …let’s ignore binary and trinary systems, OK?
  34. One to One Remember the MTI scheme? Like I said

    then, these related models come with a one-to-one relationship automatically set up. One-to-one relationships are almost like having an entire other record as an attribute on your record. They’re just foreign keys under the hood but they’re unique. Each record only relates to one other record and vice versa. One of the best examples for 1-to-1 relationships is a profile model. Back before Django had custom user models, if you wanted to store some extra bit of info about a user, you had to make a new model and you’d give it a OneToOneField to the User model. When you created a new user, you’d create a new profile instance, too.
  35. Many to Many The next kind of relationship is a

    Many to Many. M2M relationships let you have lots of related records that can also be related to lots of other records themselves. One of the most useful parts of of M2M records is the through table. Normally, Django creates a through table for you automatically that has a foreign key to each of the related tables. But you can make your own through table if you want that holds other bits of data. For example, this UserExercise table for linking users to exercises with an extra field that’ll log when each record is created. Now, normally you’d have a ManyToMany field on your model. I’m not using one here so that means I’ll have to make this record manually each time. Eh, you win some, you lose some.
  36. Generic Foreign Key And, lastly, a foreign key type that

    you probably shouldn’t use. Generic foreign keys, or GFKs, are foreign keys that don’t know what model they point to. This requires a couple of lookups and they’re not very performant. Also, you’re usually better served building more models than you are using GFKs. Occasionally they are legitimately needed, though, usually in reusable, third-party packages
  37. OK, ready to dive down a little further? You can

    stop me to ask questions at any time and I’ll expect questions when you see this icon.
  38. Selecting
 Related Records Every time you travel through a relationship,

    no matter which of the three kinds of relationship it is, you’ll have to perform another query. And that query might be a large one. There are two ways to make this a bit nicer.
  39. select_related The first, and usually most useful, is select_related which

    does a larger query initially, using a subquery to select the related records in the same database query. Most of the time, your database will be fast enough that pulling the records there will be faster than doing an entire new query. select_related queries are done from the model that doesn’t have the foreign key on it. You add select_related onto your queries like this.
  40. Recipe.objects.select_related( ‘ingredients’, ‘ingredients__ingredient’ ).filter( ingredients__ingredient__name__icontains=‘spinach’, cook_time__lte=60, prep_time__lte=15 ) You add

    select_related into the query and then list the fields that point to the related records. In this case, “ingredients” is the related field. Notice, too, that I went from ingredients to the ingredient that’s related through a double underscore relationship.
  41. prefetch_related Since select_related is for queries to the model without

    the foreign key, how do you handle selecting records with the foreign key? Well, you use prefetch_related. The API is exactly the same, you list the records you want in the prefetch_related command. Instead of making a larger query, though, Django will do completely separate, extra queries and the join them together in Python.
  42. OK, ready to dive down a little further? You can

    stop me to ask questions at any time and I’ll expect questions when you see this icon.
  43. django-debug-toolbar A really handy tool for finding places where you

    have too many queries or queries you didn’t expect is django-debug-toolbar. [check out the 2 tag]
  44. Signals One of the things you can see in django-debug-toolbar

    is any signals that were caused during the execution of the current view. Signals are similar to web hooks or callbacks but a bit more passive. Something happens, like a model instance is saved, and Django announces, or signals, that. Then anything that’s listening for the “model saved” signal gets evaluated. This is a great way to handle one-to-one relationships.
  45. OK, ready to dive down a little further? You can

    stop me to ask questions at any time and I’ll expect questions when you see this icon.
  46. Forms Forms are a really handy way of getting information

    from users and also validating data from users or other outside sources.
  47. Standard Forms You can make forms with any fields you

    want using the forms library. Django provides a ton of fields for all of the different types of inputs you might need to accept.
  48. Model Forms Easier, though, is to use Model Forms. Model

    Forms turn your models into forms. This lets you automatically take model-appropriate input, pre-fill them with instance data, and save or update instances directly from a form. Models forms, though, sadly don’t call a model’s clean() method.
  49. Validation So, what about validating data? Form fields automatically know

    how to tell if their data is the correct type. IntegerFields only take integers. URLFields have to get URLs.
  50. Form.clean() Every form can have a method named clean(). This

    method is called after all of the fields have validated themselves so you can use self.cleaned_data to get all of the valid data. This is also used for cleaning multiple fields together, like making sure two password fields match
  51. clean_fieldname() If you need to handle something above and beyond

    the default field cleaning (like making sure an integer is between 1 and 5), you can clean an individual field.
  52. Validators Or you can apply a validator to a field.

    Django comes with a bunch of built-in validators and you can write your own, too. This is generally the best idea if you’re going to have the same kind of validation/cleaning on multiple fields in multiple forms. Your validators can be used on model fields, too, which brings me to…
  53. Model clean() You can also specify how a model should

    clean itself. Again, once the validators on fields, and the field validation, too, have been run, whatever is in Model.clean() is run if you’re using ModelForm.clean(). Model.save() does not run Model.clean() or Model.full_clean(). Model.full_clean() checks uniqueness constraints, too.
  54. OK, ready to dive down a little further? You can

    stop me to ask questions at any time and I’ll expect questions when you see this icon.
  55. Formsets Oh boy. Formsets let you have multiple forms all

    based on the same form. Maybe you have a way to add or edit multiple images attached to a blog post. Each image has an ImageField, a description, and a citation/credit field. You can use a formset to show all of the forms inside of the bigger form for editing the blog post itself. Where it gets tricky is with inline model formsets. They’re model forms, in a formset (so you have a lot of them) and they’re validated, etc, as part of the larger form. I recommend avoiding this if you can. The one place where formsets are cool is the admin. The admin takes care of pretty much all of the heavy lifting for you, so they’re not so bad.
  56. OK, ready to dive down a little further? You can

    stop me to ask questions at any time and I’ll expect questions when you see this icon.
  57. Templates Alright, let’s talk about templates. Templates are text files

    that Django renders into a single file. They have a bit of data that comes in that’s called “context”. They don’t have to be HTML. Django is fully capable of rendering JSON, XML, etc. Usually, though, you’re gonna want to do that stuff a more natural way.
  58. {% Logic and Output }} Django templates use two types

    of signifiers around values and these have two different meanings. {% tags, for lack of a better work, call a bit of Python. These do things like IFs or FOR loops. Variables that are enclosed in {{ are echoed into the template. You can think of these as print() functions.
  59. {{ Template|filters }} Along with the ability to print out

    things, Django templates can also use filters. Filters apply a bit of Python logic to a value, like capitalizing the first letter of each word or sorting a list.
  60. Custom Filters Eventually, you’re gonna come up with your own

    transformation that you need to apply to data in your templates. You can make a custom filter! Custom filters live in your app’s templatetags directory, usually in the same module as your custom tags. Markdown thing
  61. Custom Tags What was that about custom tags? Yeah, you

    can make your own tags, too. So if you need a templatetag that automatically renders Markdown to HTML or sends images through a bit of code that turns them into ASCII art or whatever, you can do it.
  62. Simple Tags The simplest version of a custom templatetag is

    the simple tag. I know, surprising. Simple tags take an argument, if they need to, and then they return something that’s printed out to the template as a string.
  63. Inclusion Tags One of the most common types of custom

    tags, though, is the inclusion tag. These tags render another template into the current template. If you’ve used PHP, this is pretty similar to using PHP’s include, require, or require_once keywords. Your inclusion tag’s template can be given a context, too, so you can send data through to it if it needs it. These are really common for things like menus.
  64. Context Processor A part of Django that a lot of

    people don’t know about is the context processors. These are used to provide some default and extra information when you render a template. These do things like provide you with the “user” variable in your template so you can check if a user is logged in, the media and static contexts so you can refer to uploaded or static media, and the messages context so you can display flash messages to users. You can write your own context processor, too, if you find yourself needing a particular variable or value available in almost every template you render.
  65. Messages Django has the ability to create temporary or flash

    messages for your users using something known as the messages framework. You have several types of messages: debug, info, warning, etc. These messages are stored in the session and only shown once.
  66. Views Alright, so this is probably our biggest subject. Let’s

    talk about views! Views control how Django responds to HTTP requests. They usually interact with the database, handle validating forms, rendering templates, and, eventually, returning some sort of HTTP response. That whole thing I just talked about is called the request/response cycle. Let’s take a look at it in more depth.
  67. GET /recipes/5 So first the client makes a request. They

    say “hey, give me whatever’s at /recipes/5
  68. GET /recipes/5 You’ve set up your server so that any

    non-static file requests (so no CSS, JavaScript, etc) get sent to a WSGI server. This is your Django’s projects wsgi.py. So now the GET request for /recipes/5 is handed to Django.
  69. Middleware And now Django creates an object that represents the

    request and sends it through all of your middlewares. Middleware are small bits of code that can run checks against the request or manipulate it in small ways, like adding trailing slashes or making sure that all POST requests have a CSRF token. process_request, process_view
  70. URLs OK, so, the request has been created and Django’s

    middlewares have made sure that everything is good-to-go. Now Django takes the incoming URL, minus the domain name, and starts to match it, from top to bottom in that project-wide urls.py file, to find a route that matches. If none match, Django sends out a 404 response. Assuming one matches, Django sends the request, and any variables pulled out through the route’s regex, to the view.
  71. View And View & Template Middleware Now the view has

    the request and any variables that were in the URL. The view talks to the models, their managers, and ultimately the database. That’s all handled by the ORM, as you already know. The view pretty much always renders a template and then returns that as an HTTP response. Now Django has a response object instead of a request object.
  72. Middleware And that response object goes back through the middlewares

    but now from bottom to top. This pass through the middleware collection handles stuff like gzipping the response. process_exception, process_template_response, process_response
  73. GET /recipes/5 And then the data gets back to the

    client. Ideally, this whole trip takes less than a second.
  74. Exceptions Now, at any point in that cycle after the

    request gets to the view and until the response gets back to the middleware, if an exception occurs the request or response jumps over to the exception middleware. This is where you get things like the handy dandy 500 error page.
  75. @login_required def create_recipe(request): . . . return render(request, “recipe_form.html”, {“form”:

    form}) As you’ve probably seen, views are often just functions. They take at least one argument, the request object, and they return something. If you’re old school, you can render a template with a Context object (big C context), and then return an HttpResponse object. Or you can just use the render() function and return that since it generates an HttpResponse object itself. Function-based views are pretty simple and very easy to get into if you’re a little comfortable with Python. If you need to protect them, Django provides some authentication decorators that you can use.
  76. url(r”^recipe/create/$”, views.create_recipe) And this is how you create a URL

    for a function-based view. I’ll be surprised if you haven’t seen this.
  77. class CreateRecipeView(views.CreateView): model = models.Recipe Alternatively, you can make views

    as classes. This is my preferred method but both are valid. Class-based views, or CBVs, are really handy when you have a lot of views that follow a pattern. Because of this Django provides generic views as classes that you can use.
  78. url(r”^recipe/create/$”, views.CreateRecipeView.as_view() ) CBVs have a slightly different way of

    setting up routes for them. This is an interesting bit about views, though: they’re always, at the end of the day, a function.
  79. class CreateRecipeView( mixins.LoginRequiredMixin, views.CreateView ): model = models.Recipe Unfortunately, decorating

    a CBV isn’t super-easy. Django provides a few mixins for adding auth requirements to your class-based views. There are mixins for requiring users to be logged in, requiring them to have a particular permission, or requiring them to pass some ad hoc test.
  80. django-braces And then to pat myself on the back, if

    you love class-based views but want more than just authentication mixins, check out django-braces. There are mixins in there for handling prefetch_related and all sorts of other stuff.
  81. Admin Alright, so, how about the admin? How many of

    you have used the admin? How many of you have customized the admin? First, let’s look at how to set up basic model admins.
  82. fields/exclude fieldsets filter_horizontal filter_vertical inlines list_display list_display_links list_editable list_filter search_fields

    Let’s talk about some of the common attributes you might set on a model admin. Most of these can be controlled through methods, too, if you need to do something more custom.
  83. Admin actions You’ve probably seen the default actions that are

    in the admin: namely you can select multiple records and then choose to delete them all. You can create custom actions, too, that act on a queryset. This is a great way to have a publish step or notify step if your app needs to control publication status or something.
  84. Admin templates And, to further customize the admin, you can

    totally override the templates. If you have an admin/ directory in a non-project templates directory, the templates in there will be applied to the whole admin. Or you can override app-specific templates in an admin/ directory inside of the app’s templates/ directory. This is really handy if you want to, say, have a like Markdown preview or the ability to edit images inside the admin.
  85. Registration You can use Django’s built-in User class or you

    can write your own. Django’s registration flow is pretty customizable and packages like django-registration or django- allauth can give you a good shortcut to getting users into your site.
  86. Authentication Once you have users, you’ll need to authenticate them.

    Django allows you to set up new authentication backends if, for example, you need to authenticate users against an LDAP or something. Authentication generally has two steps. You authenticate the user with their provided credentials, and then use the login function to actually generate their authenticated session. When they’re done, you can use the logout function to remove that authenticated session.
  87. Permissions Once users are authenticated, they can be checked for

    permissions. Django ships with three “classes” of users. Superusers, like you make when you start your project, can do anything they want on your site. They are assumed to have all permissions. Next are authenticated users. Each of them, according to their own personal permissions and the permissions of the Group they belong to, can do particular things around your site. Maybe they can create recipes but they can’t delete them, for instance. And, lastly, Django has an anonymous user. These users are not authenticated and generally aren’t allowed to do anything. Django doesn’t come with object- or row-level permissions, so you can’t automatically say “OK, Jill, you can edit the blog posts that you wrote, but not the one’s that Omar wrote”. Packages like django-guardian make this possible and fairly easy. You can also write checks like this into your views, mixins, or model managers.
  88. Passwords One of my favorite security features of Django is

    the password system. Django comes with a really strong password hashing algorithm already set up, PBKDF2. But, let’s fast forward 2 or 5 or 10 years to when PBKDF2 is no longer optimal, like how MD5 and SHA1 aren’t now. Django can ship a new default hasher, or you can change the hashing algo yourself, and when your user logs in for the next time, Django will update their stored hash.
  89. XSS, CSRF, & Clickjacking Unrelated to users, Django offers some

    very handy bits of Web security out of the box. XSS, or cross-site scripting, is when someone tries to inject a bit of client-side code into your site to trick users. Maybe they run a bit of JS to capture your banking cookies. Django automatically escapes strings before displaying them, unless you turn it off (you should rarely turn it off), which stops their scriptkiddie onclick from actually being rendered as code. CSRF, cross-site request forgery, stops baddies from sending data from another site into your site, so they can’t try to get someone else’s login session for awesomesite.com by sending through a username and password from fakesite.com with a visually similar URL. CSRF generates a token that comes along with all POST requests. If Django doesn’t recognize the CSRF, or doesn’t get one, it’ll reject the request. And, lastly, clickjacking prevents your site from being displayed in a frame on someone else’s site. The baddie loads your site in a transparent iframe over a part of their site to cause you to click a button you didn’t see.
  90. Gotchas, idioms, & advice This last section is a bit

    more freeform, just observations and knowledge I’ve picked up over the years.
  91. Follow patterns If your views, forms, templates, url routes, etc

    are all named in the same pattern, it makes it a lot easier for new devs to come in and help and for you to predict what something will be called. Don’t name one view “create_recipe” and the next “meal_creation”.
  92. Wheels exist I don’t mean Python wheels, although those are

    awesome, too, and you should totally use them. Django is a big community. It’s over 10 years old, too. Chances are, whatever problem you’ve run into, someone else has too. Before you start engineering some giant solution, go have a look around. This is especially true when it comes to things like async, REST apis, and caching.
  93. Cache things Speaking of caching, cache things. Cache more things.

    Cache your queries and your compiled templates, at least, once you start getting any traffic. Django and Python are amazing but, like all dynamic languages, they’re not the fastest things around. And, while not exactly caching, make sure Python isn’t responsible for serving your static files once you’re live, too.
  94. django-debug-toolbar Hey, remember this thing? Debug toolbar will get you

    out of a lot of problems. Use it when things get sticky.
  95. DRY DRY, don’t repeat yourself. Now, this isn’t a hard-and-fast

    rule. It’s OK to repeat yourself sometimes. But make sure that, most of the time, when you do the same thing more than 2 or 3 times, you abstract it out into something you can reuse, whether that’s a new function, or class, or mixin, or whatever. Maybe a whole new app! This makes it easier to test, too, because now you can test a single unit once and know that it works.
  96. Test Oh, and you are testing, right? Test everything you

    possibly can (which is a lot). Test your views, your URLs, your models, and forms if nothing else. You can save a bit of time by testing URLs and views together, sometimes even throwing in templates, but that’s not always the best idea. Still, TEST!
  97. Where to now? So, I’ve flooded you with all the

    bits and bobs of Django. Where do you go now to learn more? I have a few suggestions.
  98. Online learning There are lots of great places to learn

    Python and Django online. Treehouse, Coursera, Codecademy, Udacity, and Udemy all have Python and Django content. Youtube has a lot, too. You can also learn through resources like Learn Python the Hard Way and the official Python and Django tutorials. Also, check out the Django Girls tutorial.
  99. Books Tons of great Python and Django books out there!

    Hello Web App 1 and 2 Two Scoops of Django Python Crash Course Django Unleashed
  100. Groups Local meetup groups, PyLadies, Django Girls, CodeNewbie. Check for

    bootcamps in your area, they often do open or Q&A events where you can find out more and meet other people that are interested. And, of course, all the usual social hangouts: Facebook, Twitter, and IRC.
  101. Packages And other packages to check out if you just

    want to add more to your Django world.