Slide 1

Slide 1 text

Web Development with Python and Django Mike Pirnat • David Stanek • CodeMash 2015

Slide 2

Slide 2 text

About Us Mike Pirnat American Greetings http://mike.pirnat.com @mpirnat David Stanek Rackspace http://traceback.org @dstanek

Slide 3

Slide 3 text

Today •Iteratively build a full-featured site •Describe a feature we need •Implement a feature together •Review our example solution • Keep yours? git show tag • Follow directly? git reset --hard tag

Slide 4

Slide 4 text

Useful Links •http://docs.python.org •https://docs.djangoproject.com •https://github.com/mpirnat/django-tutorial-v2

Slide 5

Slide 5 text

Let’s Have a Show of Hands...

Slide 6

Slide 6 text

Everything* You Need to Know About Python in One Slide *(more or less)

Slide 7

Slide 7 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 8

Slide 8 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 9

Slide 9 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 10

Slide 10 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 11

Slide 11 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 12

Slide 12 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 13

Slide 13 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 14

Slide 14 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 15

Slide 15 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 16

Slide 16 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 17

Slide 17 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 18

Slide 18 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 19

Slide 19 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 20

Slide 20 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 21

Slide 21 text

from module.submodule import SomeClass class MyClass(SomeClass): "This explains what the class is about." def method(self, x, y=1): "This explains what the method does." dictionary = {'key1': 'val1', 'key2': 'val2'} if y == 1: return ["Hello", dictionary['key1']] else: return ["World", dictionary.get(x, 'val3')] instance = MyClass() for word in instance.method(42): print(word)

Slide 22

Slide 22 text

Django

Slide 23

Slide 23 text

Django?

Slide 24

Slide 24 text

Django?

Slide 25

Slide 25 text

Django! •A high-level Python web framework •Encourages rapid development and clean, pragmatic design •“For perfectionists with deadlines” •Focus on automation and DRY •Widely supported, many deployment options

Slide 26

Slide 26 text

Perhaps You’ve Heard Of... •Disqus •Instagram •Mozilla •OpenStack •Pinterest •PolitiFact.com •Rdio

Slide 27

Slide 27 text

Django •ORM •Automatic admin interface •Regex-based URL design •Templating system •Cache infrastructure •Internationalization •Command-line job framework

Slide 28

Slide 28 text

The Django Stack

Slide 29

Slide 29 text

Django

Slide 30

Slide 30 text

Django Request

Slide 31

Slide 31 text

Django Request Response

Slide 32

Slide 32 text

Django Request Response

Slide 33

Slide 33 text

Django Framework Request Response

Slide 34

Slide 34 text

Django Framework Middleware Request Response

Slide 35

Slide 35 text

Django Framework Middleware URLs Request Response

Slide 36

Slide 36 text

Django Framework Middleware URLs Views Request Response

Slide 37

Slide 37 text

Django Framework Middleware URLs Views Models Request Response

Slide 38

Slide 38 text

Django Framework Middleware URLs Views Models DB Request Response

Slide 39

Slide 39 text

Django Framework Middleware URLs Views Models Templates DB Request Response

Slide 40

Slide 40 text

Framework Middleware URLs Views Models Templates DB Tags & Filters Request Response

Slide 41

Slide 41 text

Setup

Slide 42

Slide 42 text

Download and Install •Python 3.4 – https://python.org/downloads (or get it from your Linux distro’s package manager) •Git – http://git-scm.com

Slide 43

Slide 43 text

Got Ubuntu? •Ubuntu’s Python 3.4 is currently broken •Prevents normal setup of virtual environments •We have a cloud server already set up that you can use –104.130.195.216 •Or make a new friend

Slide 44

Slide 44 text

Got Windows? •Be sure to update the PATH so that Windows can find your scripts: C:\Python34\;C:\Python34\Scripts\;C:\Python34\Tools \Scripts

Slide 45

Slide 45 text

Installing Packages •pip install package •Installed packages go into a site-packages directory in your Python lib •That’s the “system Python” by default •But different programs may need different versions of packages... •So we have virtual environments!

Slide 46

Slide 46 text

Virtual Environments •Creates an isolated Python environment with its own site-packages •Install whatever you want without fouling anything else up •Now part of the standard library

Slide 47

Slide 47 text

Create & Activate the Virtual Environment # Mac/Linux/etc... $ pyvenv django-tutorial-v2 $ cd django-tutorial-v2 $ source bin/activate # Windows > pyvenv.py django-tutorial-v2 > cd django-tutorial-v2 > Scripts\activate.bat

Slide 48

Slide 48 text

Get the Example Code # Normally... $ git init src # Today... $ git clone https://github.com/mpirnat/django-tutorial- v2.git ./src

Slide 49

Slide 49 text

Defining Requirements •requirements.txt •A basic example: MyApp Framework==0.9.4 Library>=0.2 http://someserver.org/packages/MyPackage-3.0.tar.gz

Slide 50

Slide 50 text

Installing Requirements # Still in the 'src' directory from before... # Mac/Linux/etc... $ cd src $ pip install -r requirements.txt # Windows > cd src > pip.exe install -r requirements.txt

Slide 51

Slide 51 text

Check Prerequisites # In that same 'src' directory... # Mac/Linux/etc... $ python prerequisites.py # Windows > python.exe prerequisites.py

Slide 52

Slide 52 text

Rewind to the Start of Exercises # In that same 'src' directory... $ git reset --hard exercise01.1

Slide 53

Slide 53 text

The Project...

Slide 54

Slide 54 text

“Dungeons & Djangos” •Web-based fantasy role playing game •Inspired by D&D (5E is great, btw) •We’ll build the core of the app: • character creation • user registration, login/logout • admin interface • a fancy landing page

Slide 55

Slide 55 text

1. Start the Project

Slide 56

Slide 56 text

Starting a Project •Mac/Linux: $ django-admin.py startproject projectname ./ $ python manage.py runserver •Windows: > python Scripts\django-admin.py startproject projectname > python manage.py runserver

Slide 57

Slide 57 text

git reset --hard exercise01.1 | git show solution01.1 Exercise 1.1 •Start a new project “mysite” •Run the server •Open your browser to localhost:8000

Slide 58

Slide 58 text

New Project Contents src/ mysite/ __init__.py settings.py urls.py wsgi.py manage.py

Slide 59

Slide 59 text

Start an App •Django believes strongly in separating chunks of a site into apps that can be reused •Ecosystem of reusable apps available •Create an app; from the src directory: $ python manage.py startapp myapp •Add it to INSTALLED_APPS in settings.py

Slide 60

Slide 60 text

git reset --hard exercise01.2 | git show solution01.2 Exercise 1.2 •Start a new app named “characters”

Slide 61

Slide 61 text

New App Contents src/ mysite/ characters/ __init__.py admin.py models.py tests.py <-- you should write them! views.py migrations/

Slide 62

Slide 62 text

git reset --hard exercise01.3 | git show solution01.3 Exercise 1.3 •Add the characters app to the list of INSTALLED_APPS in settings.py

Slide 63

Slide 63 text

2. Create a Character Model

Slide 64

Slide 64 text

Models •Model classes are the nouns of the system •Used to create database tables •Integrated with the ORM to interact with the database •Need to create & run migrations when adding or changing model classes

Slide 65

Slide 65 text

git reset --hard exercise02.1 | git show solution02.1 Exercise 2.1 •Create a Character model; it should have: • name – text, up to 200 characters • background – text, open-ended • level, experience_points, max_hit_points, current_hit_points – integers • strength, dexterity, constitution, intelligence, wisdom, charisma – integers • created, modified – datetimes, automatically populated • a __str__ method that returns the character’s name

Slide 66

Slide 66 text

Migrations •Propagates model changes into the database •Keeps a record of changes made to the models •Can migrate forward and backward •Formerly provided by third-party tools •New in Django 1.7, required by Django 1.9

Slide 67

Slide 67 text

Making & Running Migrations •Creating a migration for an app: $ python manage.py makemigrations •See the SQL that will be executed: $ python manage.py sqlmigrate •Run migrations: $ python manage.py migrate

Slide 68

Slide 68 text

git reset --hard exercise02.2 | git show solution02.2 Exercise 2.2 •Create a migration for the initial version of the Character model •Run the migration

Slide 69

Slide 69 text

Trying Out the Model •Start a Python shell with all the Django stuff all ready to go: $ python manage.py shell •Now we can test out our model

Slide 70

Slide 70 text

Try the Admin Interface •Django comes with a built-in admin interface to explore and manipulate models •Runs on /admin/ by default •Need to create an admin superuser: $ python manage.py createsuperuser •Need to register models in the app’s admin.py

Slide 71

Slide 71 text

git reset --hard exercise02.3 | git show solution02.3 Exercise 2.3 •Create a superuser for using the admin interface •Register the Character model for use with the admin interface •Open your browser to localhost:8000/ admin

Slide 72

Slide 72 text

3. Add Some Defaults to the Character Model

Slide 73

Slide 73 text

Worthwhile Defaults •Level •Experience points •Hit points •Stats – simulate dice rolling!

Slide 74

Slide 74 text

Anatomy of a Dice Roll

Slide 75

Slide 75 text

Anatomy of a Dice Roll 2d8+ 1

Slide 76

Slide 76 text

Anatomy of a Dice Roll 2d8+ 1 number of dice

Slide 77

Slide 77 text

Anatomy of a Dice Roll 2d8+ 1 type of die number of dice

Slide 78

Slide 78 text

Anatomy of a Dice Roll 2d8+ 1 type of die number of dice modifier

Slide 79

Slide 79 text

git reset --hard exercise03.1 | git show solution03.1 Exercise 3.1 •Add defaults to the Character model: • level – default to 1 • experience_points – default to 0 • max_hit_points, current_hit_points – default to 10 • stats (strength, dexterity, etc.) – use a function that uses Python’s random.randint to model a 3d6 dice roll

Slide 80

Slide 80 text

git reset --hard exercise03.2 | git show solution03.2 Exercise 3.2 •Extract dice rolling from stat generation so that we can model any XdY + Z dice roll •Can do it in a one-line function •Don’t panic — this is the weirdest the code gets today!

Slide 81

Slide 81 text

4. Add Alignment to the Character Model

Slide 82

Slide 82 text

Choices •When a field can have only a finite set of values that won’t change often, use choices •Can define both database native values and their human-friendly equivalents that will be displayed in the app

Slide 83

Slide 83 text

git reset --hard exercise04.1 | git show solution04.1 Exercise 4.1 •Add alignment to the Character model; it should have a fixed set of choices: • Lawful Good • Lawful Neutral • Lawful Evil • Neutral Good • Neutral • Neutral Evil •It should default to Neutral • Chaotic Good • Chaotic Neutral • Chaotic Evil

Slide 84

Slide 84 text

git reset --hard exercise04.2 | git show solution04.2 Exercise 4.2 •Create the migration to add alignment to the Character model •Run the migration

Slide 85

Slide 85 text

5. Add Race and Class

Slide 86

Slide 86 text

Foreign Keys •Use a separate model when the data is too rich for a simple set of choices •When a model (Character) can be related to only one of some other model (Race, Class), use a ForeignKey •When using the model, need an instance: hobbit = Race('hobbit').save() bilbo = Character(..., race=hobbit)

Slide 87

Slide 87 text

Foreign Keys •Have to be careful when adding non-null fields to an existing model, doubly so when it’s a ForeignKey •Migration will ask for a default •If adding a new model and an FK relationship, no defaults yet! •Do it in several steps...

Slide 88

Slide 88 text

git reset --hard exercise05.1 | git show solution05.1 Exercise 5.1 •Create very basic models for Race and Class; they should each have: • name – text, up to 200 characters • description – text, open-ended • a __str__ method that returns the name

Slide 89

Slide 89 text

git reset --hard exercise05.2 | git show solution05.2 Exercise 5.2 •Create the migration to create the Race and Class models in the database •Run the migration

Slide 90

Slide 90 text

git reset --hard exercise05.3 | git show solution05.3 Exercise 5.3 •Add a ForeignKey relationship from the Race model to the Character model •Add a ForeignKey relationship from the Class model to the Character model •Be careful about names here; “class” is a Python builtin that we don’t want to shadow

Slide 91

Slide 91 text

Data Migrations •Adding default values into a DB is best accomplished with data migrations •Allow you to reliably populate data at the right point in the evolution of the DB •To create one: $ python manage.py makemigrations --empty appname

Slide 92

Slide 92 text

git reset --hard exercise05.4 | git show solution05.4 Exercise 5.4 •Create a data migration that populates a default race (“Human”) and class (“Generic”) into the database •Run the migration

Slide 93

Slide 93 text

git reset --hard exercise05.5 | git show solution05.5 Exercise 5.5 •Create a migration to add the ForeignKey relationships for Character/Race and Character/Class •Run the migration •When prompted for a default for the FK, enter the id you want (in this case 1 to match the data migration)

Slide 94

Slide 94 text

git reset --hard exercise05.6 | git show solution05.6 Exercise 5.6 •Register the Race and Class models for use with the admin interface •What do you notice about the Class model in the admin interface?

Slide 95

Slide 95 text

git reset --hard exercise05.7 | git show solution05.7 Exercise 5.7 •Fix the pluralization of “class” in the admin interface by adding verbose_name_plural metadata to the Class model •Observe the change in the admin app •What do you notice about how the class appears when looking at a character?

Slide 96

Slide 96 text

git reset --hard exercise05.8 | git show solution05.8 Exercise 5.8 •Add a verbose_name of “class” to the Character/Class ForeignKey in the Character model •Observe the change in the admin interface

Slide 97

Slide 97 text

git reset --hard exercise05.9 | git show solution05.9 Exercise 5.9 •Create a migration to sync up the previous change •Run the migration

Slide 98

Slide 98 text

6. Inventory

Slide 99

Slide 99 text

Many-to-Many Relations •When a model (Character) can be related to many of some other model (Item), use a ManyToManyField •When using the model, need a list of instances: arkenstone = Item(name='Arkenstone').save() sting = Item(name='Sting (shortsword)').save() bilbo.inventory = [arkenstone, sting]

Slide 100

Slide 100 text

git reset --hard exercise06.1 | git show solution06.1 Exercise 6.1 •Create an Item model; it should have: • name – text, up to 200 characters • description – text, open-ended • value – integer, default to 0 • weight – integer, default to 1 • a __str__ method that returns the name •Add a ManyToMany relation between Character and Item to the Character

Slide 101

Slide 101 text

git reset --hard exercise06.2 | git show solution06.2 Exercise 6.2 •Create a migration to add the Item model and the ManyToMany relation to the database •Run the migration

Slide 102

Slide 102 text

git reset --hard exercise06.3 | git show solution06.3 Exercise 6.3 •Register the Item model for use with the admin interface •Create an Item using the admin interface •Edit a Character in the admin interface; add an item to it •Create a Character without any items in the admin interface; what do you notice?

Slide 103

Slide 103 text

git reset --hard exercise06.4 | git show solution06.4 Exercise 6.4 •Change the ManyToMany to be nullable and blank

Slide 104

Slide 104 text

git reset --hard exercise06.5 | git show solution06.5 Exercise 6.5 •Create a migration to alter the relationship •Run the migration •Observe the change in the admin app

Slide 105

Slide 105 text

7. Basic Admin Customizations

Slide 106

Slide 106 text

git reset --hard exercise07.1 | git show solution07.1 Exercise 7.1 •Modify the admin wiring to group character fields in meaningful groups: • name, level, class, background • max hit points, current hit points • stats (strength, dexterity, constitution, intelligence, wisdom, charisma) • experience points, inventory

Slide 107

Slide 107 text

git reset --hard exercise07.2 | git show exercise07.2 Exercise 7.2 •Make the character’s creation and modification dates appear in the admin interface •Show the creation and modification dates in a separate fieldset

Slide 108

Slide 108 text

git reset --hard exercise07.3 | git show solution07.3 Exercise 7.3 •Add more fields to the character list in the admin interface: • name • level • race • class • creation & modification dates

Slide 109

Slide 109 text

git reset --hard exercise07.4 | git show solution07.4 Exercise 7.4 •Add filters for race, class, creation, and modification date to the admin interface

Slide 110

Slide 110 text

git reset --hard exercise07.5 | git show solution07.5 Exercise 7.5 •Change the model name of Race.name to “race” •Change the model name of Class.name to “class”

Slide 111

Slide 111 text

git reset --hard exercise07.6 | git show solution07.6 Exercise 7.6 •Create the migration for adding model names to Race.name and Class.name •Run the migration

Slide 112

Slide 112 text

git reset --hard exercise07.7 | git show solution07.7 Exercise 7.7 •Add search capability to the character list in the admin interface •Make characters searchable by name, background, race, and class

Slide 113

Slide 113 text

8. Add Basic Views

Slide 114

Slide 114 text

URLs •Map URLs in requests to code that can be executed •Regular expressions! •Each app has its own urls.py

Slide 115

Slide 115 text

Views •Code that handles requests •Other frameworks often call these “controllers” •Basically a function that: • gets a request passed to it • returns text or a response

Slide 116

Slide 116 text

git reset --hard exercise08.1 | git show solution08.1 Exercise 8.1 •Create a simple view in the characters app •It can just emit “hello world” for now •Create a URL mapping for /characters/ to this view

Slide 117

Slide 117 text

git reset --hard exercise08.2 | git show solution08.2 Exercise 8.2 •Create a stub view for viewing details of a single character •The URL should include the character_id •The view should say which character_id is being displayed •The view does NOT need to query the DB

Slide 118

Slide 118 text

git reset --hard exercise08.3 | git show solution08.3 Exercise 8.3 •Change the character index view to return a list of all characters •Change the character detail view to return the requested single character

Slide 119

Slide 119 text

9. Templates & Basic Improvements

Slide 120

Slide 120 text

Django Template Language •Call a function or do logic: {% ... %} •Variable substitution: {{ bar }} •Filters: {{ foo|bar }}

Slide 121

Slide 121 text

git reset --hard exercise09.1 | git show solution09.1 Exercise 9.1 •Create a template to list characters •Change the character list view to use the template

Slide 122

Slide 122 text

git reset --hard exercise09.2 | git show solution09.2 Exercise 9.2 •Create a template to show the details of a character •Change the character detail view to use the template

Slide 123

Slide 123 text

git reset --hard exercise09.3 | git show solution09.3 Exercise 9.3 •Change the character details template to show a character’s inventory

Slide 124

Slide 124 text

Relations in Templates •When a model object retrieved from the ORM has relations, you get a relation manager and not an actual iterable collection •Need to call .all() (or get or filter) on it before you get back the related model objects

Slide 125

Slide 125 text

Optimizing Queries •Be careful using relations in loops in templates; can result in many extra queries •Go read up on: • select_related: does a join in SQL • prefetch_related: queries in advance, caches results, allows “join” in Python

Slide 126

Slide 126 text

git reset --hard exercise09.4 | git show solution09.4 Exercise 9.4 •Change the character details view to return a 404 if it can’t find a character

Slide 127

Slide 127 text

git reset --hard exercise09.5 | git show solution09.5 Exercise 9.5 •Change the character details view to use the get_object_or_404 shortcut

Slide 128

Slide 128 text

git reset --hard exercise09.6 | git show solution09.6 Exercise 9.6 •Change the templates to use dynamically generated URLs in links

Slide 129

Slide 129 text

git reset --hard exercise09.7 | git show solution09.7 Exercise 9.7 •Add a namespace to the characters app URLs to prevent collisions with other apps •Update dynamic links in templates to include the namespace

Slide 130

Slide 130 text

10. Add a Basic Form to Create Characters

Slide 131

Slide 131 text

Form Validation •Why? •Classes for each kind of input field •Form class to gather input fields •View uses the form class to validate inputs

Slide 132

Slide 132 text

git reset --hard exercise10.1 | git show solution10.1 Exercise 10.1 •Create a page with a simple form to create new characters •Just show minimal fields (name, background) for now •Default race and class to the defaults we created earlier •Redirect to the character list

Slide 133

Slide 133 text

git reset --hard exercise10.2 | git show solution10.2 Exercise 10.2 •Change how race and class are set to reduce the number of database queries during character creation

Slide 134

Slide 134 text

Class-Based Views • Separate methods for separate HTTP methods instead of conditional logic • Ease development for common cases • Enables advanced designs • Optional; our example code today doesn’t use them

Slide 135

Slide 135 text

11. Refactor Views to Reduce Boilerplate

Slide 136

Slide 136 text

Generic Views •Many views fall into the same patterns •Django provides generic view classes for things like showing a list of objects, creating an object, updating an object, deleting, etc. •Subclass and set properties or override certain methods to customize

Slide 137

Slide 137 text

git reset --hard exercise11.1 | git show solution11.1 Exercise 11.1 •Change the character list to use a generic ListView •Change the character detail view to use a generic DetailView

Slide 138

Slide 138 text

git reset --hard exercise11.2 | git show solution11.2 Exercise 11.2 •Change the character list queryset to order results by character name

Slide 139

Slide 139 text

git reset --hard exercise11.3 | git show solution11.3 Exercise 11.3 •Change the character creation view to use a generic CreateView

Slide 140

Slide 140 text

12. Make Forms More Efficiently

Slide 141

Slide 141 text

Model Forms •Forms must declare every field explicitly •ModelForms read a model and automatically create the necessary fields •Can quickly customize •Use with caution; exclude fields which should not be visible/editable

Slide 142

Slide 142 text

git reset --hard exercise12.1 | git show solution12.1 Exercise 12.1 •Refactor character creation to use a ModelForm

Slide 143

Slide 143 text

git reset --hard exercise12.2 | git show solution12.2 Exercise 12.2 •During character creation, only show the fields the user can choose: • name • background • race • class • alignment

Slide 144

Slide 144 text

git reset --hard exercise12.3 | git show solution12.3 Exercise 12.3 •Show the stats (strength, dexterity, constitution, intelligence, wisdom, charisma) as read only during character creation •The solution is for illustration only; it has some security issues outside of our scope

Slide 145

Slide 145 text

13. Update & Delete Characters

Slide 146

Slide 146 text

git reset --hard exercise13.1 | git show solution13.1 Exercise 13.1 •Create a page to update characters using a generic UpdateView

Slide 147

Slide 147 text

git reset --hard exercise13.2 | git show exercise13.2 Exercise 13.2 •Create a page to delete characters using a generic DeleteView

Slide 148

Slide 148 text

14. User Registration

Slide 149

Slide 149 text

No Need to Reinvent •Django comes with a robust user framework: django.contrib.auth •Registration •Login/Logout •Password Recovery •Etc.

Slide 150

Slide 150 text

git reset --hard exercise14.1 | git show solution14.1 Exercise 14.1 •Start a new “accounts” app for managing user accounts

Slide 151

Slide 151 text

git reset --hard exercise14.2 | git show solution14.2 Exercise 14.2 •Create a page for registering users •Use django.contrib.auth’s user creation form •Provide our own template and view; base the view on a generic FormView •Don’t forget URLs and settings.py!

Slide 152

Slide 152 text

The User Object •Always have one in every request •Always available to templates •Can be anonymous or populated depending on whether the user has authenticated

Slide 153

Slide 153 text

git reset --hard exercise14.3 | git show solution14.3 Exercise 14.3 •Change the character list template •Show the username when signed in •Show the registration link when signed out

Slide 154

Slide 154 text

15. User Login & Logout

Slide 155

Slide 155 text

More Reusable Goodness •django.contrib.auth provides URLs and views for login and logout •Will want to provide our own templates

Slide 156

Slide 156 text

git reset --hard exercise15.1 | git show solution15.1 Exercise 15.1 •Enable user login and logout •Create templates for login and logged out pages •Use django.contrib.auth views •Link to the login/logout in the character list template •Try it out; what do you observe?

Slide 157

Slide 157 text

git reset --hard exercise15.2 | git show solution15.2 Exercise 15.2 •Change the default login redirect URL to the character list page (/characters)

Slide 158

Slide 158 text

git reset --hard exercise15.3 | git show solution15.3 Exercise 15.3 •Fix the template resolution order for logout

Slide 159

Slide 159 text

git reset --hard exercise15.4 | git show solution15.4 Exercise 15.4 •Create a base template for the site •Change all existing templates to extend the base template •Move the header navigation block (with our login/logout and registration links) to the base template

Slide 160

Slide 160 text

16. Let Users OWN Characters

Slide 161

Slide 161 text

git reset --hard exercise16.1 | git show solution16.1 Exercise 16.1 •Add a ForeignKey relationship between Characters and Users

Slide 162

Slide 162 text

git reset --hard exercise16.2 | git show solution16.2 Exercise 16.2 •Create the migration to add the Character/ User relationship •Run the migration

Slide 163

Slide 163 text

git reset --hard exercise16.3 | git show solution16.3 Exercise 16.3 •Add the User that created a Character to the admin fields

Slide 164

Slide 164 text

git reset --hard exercise16.4 | git show solution16.4 Exercise 16.4 •Add the player username to the player details page

Slide 165

Slide 165 text

git reset --hard exercise16.5 | git show solution16.5 Exercise 16.5 •Require the user to be logged in when creating, editing, or deleting a character

Slide 166

Slide 166 text

git reset --hard exercise16.6 | git show solution16.6 Exercise 16.6 •When creating a character, save the user who created the character

Slide 167

Slide 167 text

17. Restrict Object Access

Slide 168

Slide 168 text

Model Managers •A place to encapsulate data queries •Extend to provide extra queries with developer-friendly interfaces •Generic views can restrict access by limiting the queryset available in the view

Slide 169

Slide 169 text

git reset --hard exercise17.1 | git show solution17.1 Exercise 17.1 •Create a model manager for the Character model •Use the model manager to lock down the edit and delete functions

Slide 170

Slide 170 text

git reset --hard exercise17.2 | git show solution17.2 Exercise 17.2 •Remove the edit and delete character links when the user doesn’t own the character

Slide 171

Slide 171 text

18. Finishing Touches

Slide 172

Slide 172 text

git reset --hard exercise18.1 | git show solution18.1 Exercise 18.1 •Add a basic landing page on the root URL •Include a spiffy logo image

Slide 173

Slide 173 text

git reset --hard exercise18.1 | git show solution18.2 Exercise 18.2 •Make sure our pages have awesome branding •Put a small logo on every page

Slide 174

Slide 174 text

19. Bonus / Ideas

Slide 175

Slide 175 text

git reset --hard bonus | git show bonus Bonus Ideas •User profiles •Character pictures •Parties (groups of characters) •Rooms/locations •Combat •Loot! •Experience points/ leveling up •Weapons & armor •Race and class, for real •Spells •Multi-classing •REST API

Slide 176

Slide 176 text

No content

Slide 177

Slide 177 text

A Little Bit About Deployment

Slide 178

Slide 178 text

Django

Slide 179

Slide 179 text

Django

Slide 180

Slide 180 text

Django

Slide 181

Slide 181 text

Django Django Gunicorn Django or uwsgi!

Slide 182

Slide 182 text

Django Django Nginx Gunicorn Django or uwsgi!

Slide 183

Slide 183 text

Django Django Nginx Static Files Gunicorn Django or uwsgi!

Slide 184

Slide 184 text

Django Django Nginx Static Files Gunicorn Django Varnish or uwsgi!

Slide 185

Slide 185 text

Where to Deploy •Gondor.io •Heroku •Webfaction •Your favorite VPS (Rackspace, AWS, etc.) •Google App Engine (if that’s what you’re into)

Slide 186

Slide 186 text

Production Advice •Don’t enable admin in production •Don’t enable debug in production •Don’t enable the Django Debug Toolbar in production •Don’t publish your production settings & secrets on github

Slide 187

Slide 187 text

Questions?

Slide 188

Slide 188 text

Links •http://python.org •https://djangoproject.com •https://github.com/mpirnat/django-tutorial-v2

Slide 189

Slide 189 text

Credits • Image from Django Unchained by Sony Pictures http://www.nydailynews.com/entertainment/tv-movies/django-star-foxx-life- built-race-article-1.1220275 • Image of Django Reinhardt by ~Raimondsy http://raimondsy.deviantart.com/art/Django-Reinhardt-314914547 • Image of Gaming Dice http://www.clker.com/cliparts/R/y/7/z/q/z/role-playing-dice-hi.png • Other images from ClipArt Etc. http://etc.usf.edu/clipart/

Slide 190

Slide 190 text

Contact Information Mike Pirnat American Greetings http://mike.pirnat.com @mpirnat David Stanek Rackspace http://traceback.org @dstanek

Slide 191

Slide 191 text

Thanks for coming & happy hacking!