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. Django 101
    Kenneth Love • @kennethlove

    View full-size slide

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

    View full-size slide

  3. And I’m happy to be here!

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  6. 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!

    View full-size slide

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

    View full-size slide

  8. Large landmasses
    AKA the stuff you’ll read about the most
    Django has a few major pieces

    View full-size slide

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

    View full-size slide

  10. Forms
    Forms are used to create HTML-based inputs for users to use. They’re also use, better IMO, to validate data

    View full-size slide

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

    View full-size slide

  12. Views
    Views are the transition layer between HTTP requests and HTTP responses. In most other frameworks, they’re called “controllers”.

    View full-size slide

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

    View full-size slide

  14. Projects & Apps
    Two more words to get used to

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  21. Meal
    Recipe
    Ingredient
    Gym
    Exercise
    Sure, probably two apps: one that’s about food and another that’s about activity

    View full-size slide

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

    View full-size slide

  23. Models & the ORM
    So let’s talk about how we hold onto data, since that’s what most web apps are all about

    View full-size slide

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

    View full-size slide

  25. Queries
    Queries manipulate data. They create new records, update, or delete existing records. They also let you filter and find records.

    View full-size slide

  26. Exercise.objects.create(…)
    Recipe.objects.filter(…)
    Ingredient.objects.get(…).delete()
    Where I have the ellipses is where you’d have your conditions or attributes. Let me show you an example of each.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  29. 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?

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  47. RecipeIngredients.objects.prefetch_related(
    ‘ingredient’,
    ‘recipe’
    ).filter(
    ingredient__name__icontains=‘spinach’
    )

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  52. Forms
    Forms are a really handy way of getting information from users and also validating data from users or other outside sources.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  56. Custom Validation
    Sometimes, though, you need more than the default validation.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  59. 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…

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  65. {% 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.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  73. Questions about templates or templatetags?

    View full-size slide

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

    View full-size slide

  75. GET /recipes/5
    So first the client makes a request. They say “hey, give me whatever’s at /recipes/5

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  81. GET /recipes/5
    And then it’s back to WSGI and the server.

    View full-size slide

  82. GET /recipes/5
    And then the data gets back to the client. Ideally, this whole trip takes less than a second.

    View full-size slide

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

    View full-size slide

  84. Questions about request/response cycle?

    View full-size slide

  85. @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.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  91. Questions about function-based or class-based views or mixins?

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  96. Questions about function-based or class-based views or mixins?

    View full-size slide

  97. Users and security
    Django offers some great security and authentication bits and pieces.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  103. Questions about auth, users, security, etc

    View full-size slide

  104. Gotchas, idioms, & advice
    This last section is a bit more freeform, just observations and knowledge I’ve picked up over the years.

    View full-size slide

  105. 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”.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  108. django-debug-toolbar
    Hey, remember this thing? Debug toolbar will get you out of a lot of problems. Use it when things get sticky.

    View full-size slide

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

    View full-size slide

  110. 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!

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  115. Packages
    And other packages to check out if you just want to add more to your Django world.

    View full-size slide

  116. cookiecutter-django
    djangorestframework
    django-braces
    django-debug-toolbar

    py.test
    coverage.py
    factory-boy

    View full-size slide

  117. Questions about next steps?

    View full-size slide

  118. http:/
    /tiny.cc/hafpby
    All icons from The Noun Project
    Bye!

    View full-size slide