· 7 years ago · Sep 06, 2018, 04:30 AM
1# [THE DJANGO BOOK](https://djangobook.com/the-django-book/)
2Notes by: [Jack Kasbeer](https://jackkasbeer.co)
3___
4# [Chapter 1: Getting Started](https://djangobook.com/installing-django/)
5# The Model-View-Controller Design Pattern
6
7## Model ( M )
8Representation of your data.
9- It's not the actual data, but an interface to the data ('talks' to db
10- Usually provides an *abstraction layer* with your db so that you can use the same model with multiple db's
11
12## View ( V )
13What you see.
14- Presentation layer for your model
15- What you see on your browser for a Web app, or the UI for a desktop app
16- Provides an interface to collect user input
17
18## Controller ( C )
19Controls the flow of information b/n the model and the view (MVC should really be MCV)
20- Uses programmed logic to decide what info is pulled from the db *via the model* and what info is then passed to the view
21- Also get's information from the user *via the view* and implements business logic: either by changing the view, modifying the data through the model, OR BOTH
22- Things get messy/difficult when vastly different interpretations of what actually happens at each layer is brought into question.
23___
24
25# [Chapter 2: Django Views & URLconfs](https://djangobook.com/views-urlconfs/)
26## URLconf
27Similar to a table of elements for your Django-powered web site.
28- Mapping between URLs and the corresponding view functions that should be called
29- `include()`: allows you to include full Python import path to another `URLconf` module
30- `url()`: uses RegEx to pattern match the URL in your browser to a module in your Django project
31
32## How Django Processes a Request
33- `ROOT_URLCONF` tells Django which Python module should be used as the `URLconf` for this web site.
34- Defaulted to `'mysite.urls'` (`mysite/urls.py`)
35- When a request comes in (e.g. `/hello/`), Django loads the `URLconf` pointed to by the `ROOT_URLCONF` setting; it then checks the `URLpatterns` in order for a match..
36 .. Upon a match, it calls the view function associated with that pattern, passing it an `HttpRequest` object as the 1st param (*RECALL: view functions must return an `HttpResponse`*)..
37 .. Django does the rest, converting the Python object to a proper web response with the appropriate HTTP headers and body
38
39## Django Views: Dynamic Content
40```python
41//views.py
42from django.http import HttpResponse
43import datetime
44
45def hello(request):
46 return HttpResponse("Hello world")
47
48def current_datetime(request):
49 now = datetime.datetime.now()
50 html = "<html><body>It is now %s.</body></html>" % now
51 return HttpResponse(html)
52```
53- The `%s` within the string is a placeholder, and the percent sign after the string means “Replace the `%s` in the preceding string with the value of the variable `now`.â€
54- To add the above view `current_datetime` to `urls.py` to tell Django which URL should handle this view, we add the `URLpattern` `url('time/', current_datetime)`
55
56## URLconfs and Loose Coupling
57**Loose Coupling:** a software-development approach that values the importance of making pieces interchangeable (i.e. modularity)
58
59## Your Third View: Dynamic URLs
60How do we design our application to handle arbitrary hour offsets (for example)?
61The key is to use *wildcard URLpatterns*; `\d+` is a RegEx to match one or more digits.
62___
63
64# [Chapter 3: Django Templates](https://djangobook.com/django-templates/)
65# Django Templates
66Not a good idea to hard-code HTML directly into your views. Why:
67- Any change to the design of the page requires a change to the Python code
68- This is only a simple example
69- Writing Python code and designing HTML are two different disciplines, and most professional web development environments split these responsibilities between separate people (or even separate departments)
70- It's most efficient if programmers can work on Python code and designers can work on templates at the same time, rather than one person waiting for the other to finish editing a single file that contains both Python and HTML
71
72**This is where Django's *template system* comes in.**
73
74## Template System Basics
75A Django template is a string of text that is intended to separate the presentation of a document from its data.
76- A template defines placeholders and various bits of basic logic (*template tags*) that regulate how the document should be displayed
77- Usually used for producing HTML, but Django templates can generate any text-based format
78
79### Example: Django Template
80
81```html
82<html>
83<head>
84 <title>Ordering notice</title>
85</head>
86<body>
87 <h1>Ordering notice</h1>
88 <p>Dear {{ person_name }},</p>
89 <p>Thanks for placing an order from {{ company }}. It's scheduled to ship on {{ s\
90hip_date|date:"F j, Y" }}.</p>
91 <p>Here are the items you've ordered:</p>
92 <ul>
93 {% for item in item_list %}
94 <li>{{ item }}</li>{% endfor %}
95 </ul>
96 {% if ordered_warranty %}
97 <p>Your warranty information will be included in the packaging.</p>
98 {% else %}
99 <p>
100 You didn't order a warranty, so you're on your own when the products inevitably stop working.
101 </p>
102 {% endif %}
103 <p>Sincerely,<br />{{ company }}</p>
104</body>
105</html>
106```
107
108Basic HTML with some variables and template tags. Stepping through it:
109- `{{ variable }}`: insert the value of *variable* with the given name
110- `{% template tag %}`: "template system, do something." (very broad)
111- a `for` tag works very much like a for statement in Python
112- an `if` tag acts as a logical "if" statement
113
114## Using the Template System
115*(Popular alternative: [Jinja2](http://jinja.pocoo.org/))*
116A project can be configured with one or more template engines, but Django ships with a built-in backend for its own template system - the *Django Template Language(DTL).* Django's `contrib` apps includes templates that all use DTL.
117[Advanced Template Topics -- see Ch. 8]
118
119Here is the most basic way you can use Django's template system in Python code:
1201. Create a `Template` object by providing the raw template code as a string.
1212. Call the `render()` method of the `Template` object with a given set of variables (the context) .e.g. via Python interactive interpreter:
122```
123>>> from django import template
124>>> temp = template.Template('My name is {{ name }}.')
125>>> ctx = template.Context({'name': 'Nige'})
126>>> print (temp.render(ctx))
127My name is Nige.
128>>>
129```
130
131## Creating Template Objects
132```
133>>> from django.template import Template
134>>> t = Template('My name is {{ name }}.')
135>>> print (t)
136>>> <django.template.base.Template object at 0x107010f98>
137```
138*That* `0x107010f98` *is actually the Python "identity" of the Template object.*
139
140`TemplateSyntaxError` exceptions will be raised if `Template()` is formatted incorrectly. These cases include:
141* Invalid tags
142* Invalid arguments to valid tags
143* Invalid filters
144* Invalid arguments to valid filters
145* Invalid template syntax
146* Unclosed tags (for tags that require this)
147
148e.g. (via Python interactive interpreter):
149```
150>>> from django.template import Template
151>>> t = Template('{% notatag %}')
152Traceback (most recent call last):
153File "", line 1, in ?
154...
155django.template.exceptions.TemplateSyntaxError: Invalid block tag on line 1: 'notatag'. Did you forget to register or load this tag?
156```
157"Block tag" and "template tag" are synonymous, i.e., variable `notatag` DNE.
158
159## Rendering a Template
160Once you have a `Template` object, you can pass it data by giving it a *context.* A context is a set of template variable names and their associated values; they're used by the template to populate variables & evaluate tags (represented in Djdango by the `Context` class). `Context` has one optional arg: a dictionary mapping variable names to variable values.
161
162**TEMPLATE renders the CONTEXT:**
163`template_var.render(context_var)`
164
165## Dictionaries & Contexts
166A Python dictionary is a mapping b/n known keys and variable values.
167*Contexts are similar but provide additional functionality.* [See Ch. 8]
168e.g., `Context` constructor takes a Python dictionary, which maps variable names to values:
169```python
170c = Context({'person_name': 'John Smith'`C,
171... 'company': 'Outdoor Equipment',
172... 'ship_date': datetime.date(2017, 7, 2),
173... 'ordered_warranty': False})
174```
175
176**Healthy reminder**
177Whenever you're using the same template source to render multiple contexts like this, it's more efficient to create the `Template` object *once*, and then call `render()` on it multiple times:
178```
179# Bad
180for name in ('John', 'Julie', 'Pat'):
181 t = Template('Hello, {{ name }}')
182 print (t.render(Context({'name': name})))
183
184# Good
185t = Template('Hello, {{ name }}')
186for name in ('John', 'Julie', 'Pat'):
187 print (t.render(Context({'name': name})))
188```
189Django's template parsing is quite fast.
190
191## Context Variable Lookup
192**The key to traversing complex data structures in Django templates is the dot character (".").** Use a dot to access dictionary keys, attributes, methods, or indices of an object. By example...
193
194*Dictionary keys*
195Suppose you're passing a Python dict to a template. Access the values of that dict by dict key, us a dot:
196```
197>>> from django.template import Template, Context
198>>> person = {'name': 'Sally', 'age': '43'}
199>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
200>>> c = Context({'person': person})
201>>> t.render(c)
202'Sally is 43 years old.'
203```
204
205*Attributes*
206A Python `datetime.date` object has `year`, `month`, and `day` attributes, and you can use a dot to access those attributes in a Django template:
207```
208>>> from django.template import Template, Context
209>>> import datetime
210>>> d = datetime.date(2017, 5, 2)
211>>> d.year
2122017
213>>> d.month
2145
215>>> d.day
2162
217>>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
218>>> c = Context({'date': d})
219>>> t.render(c)
220'The month is 5 and the year is 2017.'
221```
222
223*Indices of an arbitrary object*
224This example uses a custom class, demonstrating that variable dots also allow attribute access on arbitrary objects:
225```
226>>> from django.template import Template, Context
227>>> class Person(object):
228... def __init__(self, first_name, last_name):
229... self.first_name, self.last_name = first_name, last_name
230>>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
231>>> c = Context({'person': Person('John', 'Smith')})
232>>> t.render(c)
233'Hello, John Smith.'
234```
235
236*Methods*
237Each Python string has methods `upper()` and `isdigit()`, and you can call those in Django templates using the same dot syntax:
238```
239>>> from django.template import Template, Context
240>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
241>>> t.render(Context({'var': 'hello'}))
242'hello -- HELLO -- False'
243>>> t.render(Context({'var': '123'}))
244'123 -- 123 -- True'
245```
246**Summarizing 'dot lookups':**
247* Dictionary lookup >>> `foo["bar"]`
248* Attribute lookup >>> `foo.bar`
249* Method call >>> `foo.bar()`
250* List-index lookup >>> `foo[2]`
251
252## Method Call Behavior
253Method calls are slightly more complex than the other lookup types. Here are some things to keep in mind:
254- If, during the method looup, a method raises an exception, the exception will be propagated, unless the exception has an attribute `silent_variable_failure` whose value is `True`. The variable would then render as the default, an empty string. For example:
255```
256 >>> t = Template("My name is {{ person.first_name }}.")
257>>> class PersonClass3:
258... def first_name(self):
259... raise AssertionError("foo")
260>>> p = PersonClass3()
261>>> t.render(Context({"person": p}))
262Traceback (most recent call last):
263...
264AssertionError: foo
265
266>>> class SilentAssertionError(Exception):
267... silent_variable_failure = True
268>>> class PersonClass4:
269... def first_name(self):
270... raise SilentAssertionError
271>>> p = PersonClass4()
272>>> t.render(Context({"person": p}))
273'My name is .'
274```
275- A method call will only work if the method has no required arguments.
276- By design, Django intentionally limits the amount of logic processing available in the template, so it’s not possible to pass arguments to method calls accessed from within templates. Data should be calculated in views and then passed to templates for display.
277- Say, for instance, you have a `BankAccount` object that has a `delete()` method. If a template includes something like `{{ account.delete }}`, where `account` is a `BankAccount` object, the object would be deleted when the template is rendered! To prevent this, set the function attribute `alters_data` on the method:
278```python
279def delete(self):
280 # Delete the account
281 delete.alters_data = True
282```
283
284**NOTE:** The dynamically-generated `delete()` and `save()` methods on Django model objects get `alters_data=true` set automatically.
285___
286
287# Django Template Tags & Filters
288THe most common tags and filters.
289
290## Tags
291### if/else
292An `{% else %}` tag is optional, unless there are `{% elif %}`'s:
293```
294{% if athlete_list %}
295 <p>Number of athletes: {{ athlete_list|length }}</p>
296{% elif athlete_in_locker_room_list %}
297 <p>Athletes should be out of the locker room soon!</p>
298{% elif ...
299...
300{% else %}
301 <p>No athletes.</p>
302{% endif %}
303```
304The `{% if %}` tag accepts `and`, `or`, or `not` for testing multiple variables, or to negate a given variable. It also accepts `in`/`not in` for testing whether a given value is or isn't in the specified container, and `is`/`is not` for testing if two entities are the same object.
305
306### for
307The `{% for %}` tag allows you to loop over each item in a sequence. As in Python’s `for` statement, the syntax is `for X in Y`, where `Y` is the sequence to loop over and `X` is the name of the variable to use for a particular cycle of the loop.
308
309For example, you could use the following to display a list of athletes given a variable `athlete_list`:
310```
311<ul>
312 {% for athlete in athlete_list %}
313 <li>{{ athlete.name }}</li>
314 {% endfor %}
315</ul>
316```
317
318If you need to loop over a list of lists, you can unpack the values in each sub list into individual variables. For example, if your context contains a list of (x,y) coordinates called `points`, you could use the following to output the list of points:
319```
320{% for x, y in points %}
321 <p>There is a point at {{ x }},{{ y }}</p>
322{% endfor %}
323```
324
325This can also be useful if you need to access the items in a dictionary. For example, if your context contained a dictionary `data`, the following would display the keys and values of the dictionary:
326```
327{% for key, value in data.items %}
328 {{ key }}: {{ value }}
329{% endfor %}
330```
331
332A common pattern is to check the size of the list before looping over it, and outputting some special text if the list is empty:
333```
334{% if athlete_list %}
335 {% for athlete in athlete_list %}
336 <p>{{ athlete.name }}</p>
337 {% endfor %}
338{% else %}
339 <p>There are no athletes. Only computer programmers.</p>
340{% endif %}
341```
342The `for` tag supports an optional `{% empty %}` clause that lets you define what to output if the list is empty. This eliminates the outer if/else chain. Equivalent to the code above:
343```
344{% for athlete in athlete_list %}
345 <p>{{ athlete.name }}</p>
346{% empty %}
347 <p>There are no athletes. Only computer programmers.</p>
348{% endfor %}
349```
350
351**NOTE:** There is no support for concepts like "break" or "continue" (see "Philosophies and Limitations").
352
353Within each `{% for %}` loop, you get access to a template variable called `forloop`. Allows access to attributes regarding the progress of the loop:
354- `forloop.counter` is always set to an integer representing the number of times the loop has been entered.
355- `forloop.counter0` is like `foorloop.counter`, except it's zero-indexed - value is set to 0 after first loop iteration (vs. 1).
356- `forloop.revcounter` is always set to an integer representing the number of remaining items in the loop. The first time through the loop, `forloop.revcounter` will be set to the total number of items in the sequence you’re traversing. The last time through the loop, `forloop.revcounter` will be set to 1.
357- `forloop.revcounter0` is analogous to `forloop.counter0` (so the last time throught he loop, it will be set to 0).
358- `forloop.first` is a Boolean value set to `True` if this is the first time through the loop.
359- `forloop.last` is a Boolean value set to `True` if this is the last time through the loop.
360- `forloop.parentloop` is a reference to the `forloop object` for the parent loop, in case of nested loops.
361
362## Comments
363- Use `{# comment goes here #}` for single-line comments.
364- Use `{% comment %}` comments can be on multiple lines here `{% endcomment %}` for mult-line comments.
365- Optional notes can be places inside multi-line comment blocks, i.e.,
366```
367{% comment "This is the optional note" %}
368 ...
369{% endcomment %}
370```
371**Comment tags cannot be nested.**
372
373## Filters
374Template filters are simple ways of altering the value of variables before they’re displayed. Filters use a pipe character, like this:
375`{{ name|lower }}`
376This displays the value of the {{ name }} variable after being filtered through the lower filter, which converts text to lowercase.
377
378Filters can be *chained* – that is, they can be used in tandem such that the output of one filter is applied to the next. For example, take the first element in a list and converts it to uppercase:
379`{{ my_list|first|upper }}`
380
381Some filters take arguments. A filter argument comes after a colon and is always in double quotes. For example:
382`{{ bio|truncatewords:"30" }}`
383This displays the first 30 words of the `bio` variable.
384
385A few of the most important filters (see Appendix E for full list):
386- `addslashes`: Adds a backslash before any backslash, single quote, or double quote. This is useful for escaping strings. For example: `{{ value|addslashes }}`.
387- `date`: Formats a `date` or `datetime` object according to a format string given in the parameter. For example: `{{ pub_date|date:"F j, Y" }}`. Format strings are defined in Appendix E.
388- `length`: Returns the length of the value. For a list, this returns the number of elements. For a string, this returns the number of characters. If the variable is undefined, `length` returns 0.
389
390## Philosophies & Limitations
391First and foremost, the **limitations to the DTL are intentional.**
392
393The original creators of Django had a very definite set of philosophies in creating the DTL:
3941. Separate logic from presentation
3952. Discourage redundancy - template system should make it easy to store elements like nav, headeer, and footer in a single place, eliminating duplicate code. This is the philosophy behind template inheritance.
3963. Be decoupled from HTML -template stystem only outputs HTML or other text-based formated, or just plain text.
3974. XML is bad - Using an XML engine to parse templates introduces a whole new world of human error in editing templates – and incurs an unacceptable level of overhead in template processing.
3985. Assume designer competence (Django expects template authors are comfortable editing HTML directly.)
3996. Treat whitespace obviously
4007. Don't invent a programming language - template system doesn't allow assignment to variables or advanced logic. Templates are assumed to be written by designers and not programmers.
4018. Ensure safety and security
4029. Extensible - philosophy behind custom template tags and filters.Django expects template authors are comfortable editing HTML directly.
403
404# Templates in Views
405## Template Loading
406Django provides a convenient and powerful API for loading templates from the filesystem. In order to use this template-loading API, first you’ll need to tell the framework where you store your templates. Do this in your `settings.py` file:
407```
408TEMPLATES = [
409 {
410 'BACKEND': 'django.template.backends.django.DjangoTemplates',
411 'DIRS': [],
412 'APP_DIRS': True,
413 'OPTIONS': {
414 # ... some options here ...
415 },
416 },
417]
418```
419Since most engines load templates from files, the top-level configuration for each engine contains three common settings:
4201. `DIRS`` defines a list of directories where the engine should look for template source files, in search order.
4212. `APP_DIRS` tells whether the engine should look for templates inside installed applications. By convention, when `APPS_DIRS` is set to `True`, `DjangoTemplates` looks for a `\templates` subdirectory in each of the `INSTALLED_APPS`. This allows the template engine to find application templates even if `DIRS` is empty.
4223. `OPTIONS` contains backend-specific settings.
423
424## Template Directories
425`DIRS`, by default, is an empty list. To tell Django’s template-loading mechanism where to look for templates, pick a directory where you’d like to store your templates and add it to DIRS, like so:
426```
427'DIRS': [
428 '/home/html/templates/site',
429 '/home/html/templates/default',
430 ],
431```
432A few things to note:
433- Unless you are building a very simple program with no apps, you are better off leaving DIRS empty. The default settings file configures APP_DIRS to True, so you are better off having a “templates†subdirectory in your Django app.
434- If you want to have a set of master templates at project root, e.g. mysite\templates, you do need to set DIRS, like so:
435`'DIRS': [os.path.join(BASE_DIR, 'templates')],`
436
437A very simple configuration to demonstrate how template loading works...
438
439First, you will have to set `DIRS` to `[os.path.join(BASE_DIR,'templates')]` as per the example above. Your settings file should now look like this:
440```
441TEMPLATES = [
442 {
443 'BACKEND': 'django.template.backends.django.DjangoTemplates',
444 'DIRS': [os.path.join(BASE_DIR,'templates')],
445 'APP_DIRS': True,
446 'OPTIONS': {
447 # ...
448```
449With `DIRS` set, the next thing to do is create a `\templates` directory inside your root `\mysite` folder. When you are finished, your folder structure should look like this:
450```
451\mysite_project
452 \mysite
453 \mysite
454 \templates
455 manage.py
456```
457Next step is to change the view code to use Django’s template-loading functionality rather than hard-coding the template paths. Change `current_datetime view`, let’s change it like so:
458```
459#mysite\mysite\views.py
460
461from django.template.loader import get_template
462from django.http import HttpResponse
463import datetime
464
465def current_datetime(request):
466 now = datetime.datetime.now()
467 t = get_template('current_datetime.html')
468 html = t.render({'current_date': now})
469 return HttpResponse(html)
470```
471Generally, you will use a Django template loader rather than using the low-level template API as in the previous examples. In this example, we’re using the function `django.template.loader.get_template()` rather than loading the template from the filesystem manually. The `get_template()` function takes a template name as its argument, figures out where the template lives on the filesystem, opens that file, and returns a compiled Template object.
472
473Also note that `get_template()` returns a backend-dependent Template from `django.template.backends.base.Template`, in which the `render()` method only accepts a dictionary object, not a `Context` object.
474
475Our template in this example is `current_datetime.html`, but there’s nothing special about that `.html` extension. You can give your templates whatever extension makes sense for your application, or you can leave off extensions entirely.
476
477To determine the location of the template on your filesystem, get_template() will look in order:
478- If `APP_DIRS` is set to `True`, and assuming you are using the DTL, it will look for a `/templates` directory in the current app.
479- If it does not find your template in the current app, `get_template()` combines your template directories from `DIRS` with the template name that you pass to `get_template()` and steps through each of them in order until it finds your template.
480- If `get_template()` cannot find the template with the given name, it raises a `TemplateDoesNotExist` exception.
481
482## render()
483To load a template, fill a Context, return an HttpResponse object with the result of the rendered template, and then optimize it to use get_template() instead of hard-coding templates and template paths is far from an ideal solution.
484
485Django’s developers recognized that, because this is such a common idiom, Django needed a shortcut that could do all this in one line of code. This shortcut is a function called `render()`, which lives in the module `django.shortcuts`.
486
487Here’s the ongoing `current_datetime` example rewritten to use `render()`:
488```
489from django.shortcuts import render
490import datetime
491
492def current_datetime(request):
493 now = datetime.datetime.now()
494 return render(request, 'current_datetime.html', {'current_date': now})
495```
496The first argument to `render()` is the request, the second is the name of the template to use. The third argument, if given, should be a dictionary to use in creating a `Context` for that template. If you don’t provide a third argument, `render()` will use an empty dictionary.
497
498## Template Subdirectories
499It can get unwieldy to store all of your templates in a single directory. You might like to store templates in subdirectories of your template directory, and that’s fine (it's actually recommended). It gives your templates their own *namespace*, the utility of which we will explore later in the book when we start building Django apps.
500
501Storing templates in subdirectories of your template directory is easy. In your calls to `get_template()`, just include the subdirectory name and a slash before the template name, like so:
502```
503t = get_template('dateapp/current_datetime.html')
504```
505
506The same thing could be accomplished with `render()`:
507```
508return render(request, 'dateapp/current_datetime.html', {'current_date': now})
509```
510
511## The include Template Tag
512A built-in template tag that takes advantage of the template-loading mechanism: `{% include %}`.
513
514> This tag allows you to include the contents of another template.
515> The argument to the tag should be the name of the template to include, and the template name can be either a variable or a hard-coded (quoted) string, in either single or double quotes.
516
517**Anytime you have the same code in multiple templates, consider using an `{% include %}` to remove the duplication.**
518
519This example includes the contents of the template `includes/nav.html`:
520```
521{% include 'includes/nav.html' %}
522```
523This example includes the contents of the template whose name is contained in the variable `template_name`:
524```
525{% include template_name %}
526```
527Relative paths are also allowed (but, *personally*, discouraged)
528```
529{% include './nav.html' %}
530{% include '../nav_base.html' %}
531```
532
533As in `get_template()`, the file name of the template is determined by either adding the path to the `\templates` directory in the current Django app (if `APPS_DIR` is `True`) or by adding the template directory from `DIRS` to the requested template name. Included templates are evaluated with the context of the template that’s including them.
534
535**NOTE**
536> There is no shared state between included templates – each include is a completely independent rendering process. Blocks are evaluated **before** they are included.
537> This means that a template that includes blocks from another will contain blocks that have **already been evaluated and rendered** – not blocks that can be overridden by, for example, an extending template.
538
539## Template Inheritance
540In essence, *template inheritance* lets you build a base “skeleton†template that contains all the common parts of your site and defines “blocks†that child templates can override.
541
542For example, to illustrate, let's first create a more complete template for our `current_datetime` view via our `current_datetime.html` file:
543```html
544<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
545
546<html lang="en">
547<head>
548 <title>The current time</title>
549</head>
550<body>
551 <h1>My helpful timestamp site</h1>
552 <p>It is now {{ current_date }}.</p>
553 <hr>
554 <p>Thanks for visiting my site.</p>
555</body>
556</html>
557```
558But now what happens if we'd like to also create a template for the `hours_ahead` view from before? We'd re-write a low of code is what would happen...
559
560**The server-side "include" solution:**
561> Factor out the common bits in both templates and save them in separate template snippets, which are then included in each template.
562
563Perhaps your store the header file in `/templates/header.html':
564```html
565<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
566<html lang="en">
567<head>
568```
569And the footer in `/templates/footer.html`:
570```html
571 <hr>
572 <p>Thanks for visiting my site.</p>
573 </body>
574</html>
575```
576
577If you noticed how the middle aspect of the document may get messy, Django’s template inheritance system solves these problems. You can think of it as an “inside-out†version of server-side includes. Instead of defining the snippets that are common, you define the snippets that are different.
578
579The **first step** is to **define a base template** – a skeleton of your page that child templates will later fill in, e.g.:
580```html
581<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
582<html lang="en">
583<head>
584 <title>{% block title %}{% endblock %}</title>
585</head>
586<body>
587 <h1>My helpful timestamp site</h1>
588 {% block content %}{% endblock %}
589
590 {% block footer %}
591 <hr>
592 <p>Thanks for visiting my site.</p>
593 {% endblock %}
594</body>
595</html>
596```
597This template, which we’ll call `base.html`, defines a simple HTML skeleton document that we’ll use for all the pages on the site.
598
599We’re using a template tag here that you haven’t seen before: the `{% block %}` tag. All the `{% block %}` tags do is tell the template engine that a child template may override those portions of the template.
600
601Using the base template, modify `current_datetime.html` template to use it:
602```html
603{% extends "base.html" %}
604{% block title %}The current time{% endblock %}
605{% block content %}
606 <p>It is now {{ current_date }}.</p>
607{% endblock %}
608```
609Here’s how it works. When you load the template `current_datetime.html`, the template engine sees the `{% extends %}` tag, noting that this template is a child template. The engine immediately loads the parent template – in this case, `base.html`.
610
611At that point, the template engine notices the three `{% block %}` tags in `base.html` and replaces those blocks with the contents of the child template. So, the title we’ve defined in `{% block title %}` will be used, as will the `{% block content %}`.
612
613Inheritance doesn’t affect the template context. In other words, any template in the inheritance tree will have access to every one of your template variables from the context. You can use as many levels of inheritance as needed. One common way of using inheritance is the following three-level approach:
6141. Create `base.html` template to hold the main "look and feel" of your site. The truly static HTML.
6152. Create `base_SECTION.html` template for each "section" of the site (e.g. latest news, faq,..). These extend `base.html` and include section-specific styles/design.
6163. Create individual templates for each type of page, such as a forum page or a photo gallery. These sections extend the appropriate section template.
617
618Guidelines for working with template inheritance:
619- If you use `{% extends %}` in a template, it must be the first template tag in that template.
620- Generally, the more {% block %} tags in your base templates, the better. It's better to have more hooks than fewer hooks.
621- If you're duplicating code, it's likely you should move that code to a `{% block %}` in a parent template.
622- If you need to get the content of the block from the parent template, use `{{ block.super }}`, which is a “magic†variable providing the rendered text of the parent template.
623- You may not define multiple `{% block %}` tags with the same name in the same template.
624- The template name you pass to `{% extends %}` is loaded using the same method that `get_template()` uses. That is, the template name is appended to your `DIRS` setting, or the `\templates` folder in the current Django app.
625- In most cases, the argument to `{% extends %}` will be a string, but it can also be a variable, if you don’t know the name of the parent template until runtime. This lets you do some cool, dynamic stuff.
626___
627
628# [Chapter 4: Django Models](https://djangobook.com/django-models/)
629Django is well suited for making database-driven web sites, because it comes with easy yet powerful tools for performing database queries using Python. This chapter explains that functionality: **Django’s database layer.**
630
631INFORMATION NOTICE
632___
633While it’s not strictly necessary to know basic relational database theory and SQL in order to use Django’s database layer, it’s highly recommended. An introduction to those concepts is beyond the scope of this book, but keep reading even if you’re a database newbie. You’ll probably be able to follow along and grasp concepts based on the context.
634
635(If I ever get bored and type my notes summarizing Ramkrishnan & Gehrke's Database Management Systems [3rd ed.] textbook's *Application emphasis* style of reading/implementing the text, I surely will... but those guys wrote a lot)
636___
637
638## The "Dumb" Way to Do Database Queries in Views
639
640An example of a very poor use of db's in a view (`book_list`):
641```python
642from django.shortcuts import render
643import MySQLdb
644
645def book_list(request):
646 db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost')
647 cursor = db.cursor()
648 cursor.execute('SELECT name FROM books ORDER BY name')
649 names = [row[0] for row in cursor.fetchall()]
650 db.close()
651 return render(request, 'book_list.html', {'names': names})
652```
653
654**Trivial issues worth noting:**
655- Hard-coding the database connection parameters (e.g. `db=my_db`)
656- Far too much boilerplate code
657- Switching from MySQL to a different database, e.g. PostgreSQL, large amounts of code will need to be re-written.
658 > Ideally, the database server we’re using would be abstracted, so that a database server change could be made in a single place. (This feature is particularly relevant if you’re building an open-source Django application that you want to be used by as many people as possible.)
659
660**Django's database layer solves these problems**
661
662## Configuring the Database
663Default setup for `settings.py` and a quick rundown (review):
664```python
665DATABASES = {
666 'default': {
667 'ENGINE': 'django.db.backends.sqlite3',
668 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
669 }
670}
671```
672- `ENGINE` tells Django with db engine to use
673- `NAME` tells Django the name of your db.
674- See Ch. 21 for a detailed description on how to set up the various db's supported by Django.
675
676## Your First App
677We've created a *project*, but now it's time to create an *app*. What's the difference? Configuration vs. code:
678- A project is an instance of a certain set of Django apps, plus the configuration for those apps.
679- An app is a portable set of Django functionality, usually including models and views, that live together in a single Python package. For example, Django comes with the automatic admin interface (an app - they're *portable*).
680
681Indeed, you don’t necessarily need to create apps at all, as evidenced by the example view functions we’ve created so far in this book. In those cases, we simply created a file called `views.py`, filled it with view functions, and pointed our URLconf at those functions. No apps were needed...
682
683> However, there’s one requirement regarding the app convention: **if you’re using Django’s database layer (models), you must create a Django app.** Models must live within apps.
684
685In the directory where your `manage.py` file lives, create an app called `books` like so on the CL:
686```
687python manage.py startapp books
688```
689The result of this command should be the following tree (more or less):
690```
691\mysite_project
692 \books
693 \migrations
694 __init__.py
695 admin.py
696 apps.py
697 models.py
698 tests.py
699 views.py
700 \mysite
701 \templates
702 manage.py
703```
704
705# [Defining Django Models in Python](https://djangobook.com/django-models#defining-django-models-in-python)
706A Django model is a description of the data in your database, represented as Python code. It’s your data layout – the equivalent of your SQL `CREATE TABLE` statements – except it’s in Python instead of SQL, and it includes more than just database column definitions.
707
708*"Isn't it redundant to define data models in Python instead of in SQL?"*
709Django works the way it does for several reasons:
710>> Introspection requires overhead and is imperfect. In order to provide convenient data-access APIs, Django needs to know the database layout somehow... explicitly describing the data in Python was chosen as the best solution.
711
712>> It helps productivity if you keep yourself in a single programming environment/mentality for as long as possible. Having to write SQL, then Python, and then SQL again is disruptive.
713
714>> Having data models stored as code rather than in your database makes it easier to keep your models under version control. This way, you can easily keep track of changes to your data layouts.
715
716>> SQL allows for only a certain level of metadata about a data layout. The advantage of higher-level data types is higher productivity and more reusable code.
717
718>> **SQL is inconsistent across database platforms.**
719
720There are drawbacks... it’s possible for the Python code to get out of sync with what’s actually in the database.
721
722Therefore, changes made inside your Django model need to *migrated* so that the model changes be reflected in your database accordingly.
723
724## Your First Model
725Suppose we have the following concepts, fields, and relatinships:
726- An author has a fir name, a last name, and an email address.
727- A publisher has a name, a street address, a city, a state/province, a country, and a web site.
728- A book has a title and a publication date. t also has one or more authors (a many-to-many relationship with authors) and a single publisher (a one-to-many relationship – aka foreign key – to publishers).
729
730### 1. Express the database layout as Python code
731The first step in using this database layout with Django is to express it as Python code. In the `models.py` file that was created by the `startapp` command, enter the following:
732```python
733from django.db import models
734
735class Publisher(models.Model):
736 name = models.CharField(max_length=30)
737 address = models.CharField(max_length=50)
738 city = models.CharField(max_length=60)
739 state_province = models.CharField(max_length=30)
740 country = models.CharField(max_length=50)
741 website = models.URLField()
742
743class Author(models.Model):
744 first_name = models.CharField(max_length=30)
745 last_name = models.CharField(max_length=40)
746 email = models.EmailField()
747
748class Book(models.Model):
749 title = models.CharField(max_length=100)
750 authors = models.ManyToManyField(Author)
751 publisher = models.ForeignKey(Publisher)
752 publication_date = models.DateField()
753```
754- The parent class, `Model, contains all the machinery necessary to make these objects capable of interacting with a database – and that leaves our models responsible solely for defining their fields, in a nice and compact syntax.
755- This is all the code we need to write to have basic data access with Django.
756- Each model generally corresponds to a single database table, and each attribute on a model generally corresponds to a column in that database table.
757- The attribute name corresponds to the column’s name, and the type of field (e.g., `CharField`) corresponds to the database column type (e.g., `varchar`).
758
759##### Important "Behind the Scenes" Intel
760The exception to the one-class-per-database-table rule is the case of many-to-many relationships.
761> In our example models, `Book` has a `ManyToManyField` called `authors`. This designates that a book has one or many authors, but the `Book` database table doesn’t get an `authors` column.
762> Rather, Django creates an additional table – a many-to-many join table – that handles the mapping of books to authors.
763
764*A full list of field types and model syntax otions can be found in [Appendix B](https://djangobook.com/database-api-reference/).*
765
766##### DON'T FORGET: Primary Keys!
767Finally, note we haven’t explicitly defined a primary key in any of these models. Unless you instruct it otherwise, Django automatically gives every model an auto-incrementing integer primary key field called `id`.
768
769## Installing the Model
770We’ve written the code; now let’s create the tables in our database. In order to do that, the first step is to *activate* these models in our Django project.
771
772### 2. Create the tables in our database
773We do that by adding the `books` app to the list of installed apps in the settings file, by adding `books.apps.BooksConfig` to `INSTALLED_APPS`. Like so:
774```python
775# settings.py
776...
777INSTALLED_APPS = [
778'django.contrib.admin',
779'django.contrib.auth',
780'django.contrib.contenttypes',
781'django.contrib.sessions',
782'django.contrib.messages',
783'django.contrib.staticfiles',
784'books.apps.BooksConfig',
785]
786...
787```
788This successfully activates the Django app in the settings file!
789
790> Each app in `INSTALLED_APPS` is represented by its full Python path – that is, the path of packages, separated by dots, leading to the app package. The dotted path in this case points to the `BooksConfig` class that Django created for you in the `apps.py` file.
791
792With the app activated in `settings.py`, we can create the database tables in our database!
7931. Validate the models:
794 ```
795 python manage.py check
796 ```
7972. Tell Django that you have made some changes to your models:
798 ```
799 python manage.py makemigrations books
800 ```
801 > Migrations are how Django stores changes to your models (and thus your db schema) - they're just files on disk.
802
803 > **Note the following:**
804 - Table names are automatically generated by combining the name of the app (`books`) and the lowercase name of the model (`publisher`, `book`, and `author`). To override see [Appendix B](https://djangobook.com/database-api-reference/).
805 - Django adds a primary key for each table automatically – the `id` fields. You can override this. By convention, Django appends `"_id"` to the foreign key field name. As you might have guessed, you can override this behavior, too.
806 - The foreign key relationship is made explit by a `REFERENCES` statement.
807
808These CREATE TABLE statements are tailored to the database you’re using, so database-specific field types such as `auto_increment` (MySQL), `serial` (PostgreSQL), or `integer primary key` (SQLite) are handled for you automatically. The same goes for quoting of column names (e.g., using double quotes or single quotes).
809
810### 3. Committing the SQL to the database:
811Done very easily in Django with the `migrate` command:
812```
813python manage.py migrate
814```
815> Note - the first time you run migrate, Django will also create all the system tables that Django needs for the inbuilt apps.
816
817**Migrations** are Django’s way of **propagating changes you make to your models (adding a field, deleting a model, etc.) into your database schema**. They’re designed to be mostly automatic, however there are some caveats. [More on migrations [Ch. 21]](https://djangobook.com/advanced-database-management/)
818
819# Once you’ve created a model, Django automatically provides a high-level Python API for working with those models. Try it out by running python manage.py shell from within your virtual environment and typing the following:
820```python
821>>> from books.models import Publisher
822>>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue',
823... city='Berkeley', state_province='CA', country='U.S.A.',
824... website='http://www.apress.com/')
825>>> p1.save()
826>>> p2 = Publisher(name="O'Reilly", address='10 Fawcett St.',
827... city='Cambridge', state_province='MA', country='U.S.A.',
828... website='http://www.oreilly.com/')
829>>> p2.save()
830>>> publisher_list = Publisher.objects.all()
831>>> publisher_list
832<QuerySet [<Publisher: Publisher object>, <Publisher: Publisher object>]>
833```
834**Highlights:**
835- Import the `Publishler` model class so we can interact with the db table that contains publishers.
836- Create a `Publisher` object by instantiating it with values for each field (e.g. `name`).
837- `save()` saves the object to the database (SQL `INSERT` statement behind the scenes)
838- To retrieve publishers from the database, use the attribute `Publisher.objects`, which you can think of as a set of all publishers. Fetch a list of all `Publisher` objects in the database with the statement `Publisher.objects.all()` (SQL `SELECT` statement behind the scenes).
839
840If you want to create an object and save it to the database in a single step, use the `objects.create()` method. This example is equivalent to the example above:
841```python
842>>> p1 = Publisher.objects.create(name='Apress',
843... address='2855 Telegraph Avenue',
844... city='Berkeley', state_province='CA', country='U.S.A.',
845... website='http://www.apress.com/')
846>>> p2 = Publisher.objects.create(name="O'Reilly",
847... address='10 Fawcett St.', city='Cambridge',
848... state_province='MA', country='U.S.A.',
849... website='http://www.oreilly.com/')
850>>> publisher_list = Publisher.objects.all()
851>>> publisher_list
852<QuerySet [<Publisher: Publisher object>, <Publisher: Publisher object>]>
853```
854
855## Adding Model String Representations
856##### A small annoyance
857When we printed out the list of publishers, all we got was this unhelpful display that makes it difficult to tell the `Publisher` objects apart:
858```python
859<QuerySet [<Publisher: Publisher object>, <Publisher: Publisher object>]>
860```
861**Easy fix:** add `__str__()` method to our `Publisher` class. This tells Python how to display a human-readable representation of an object.
862
863Only requirement is `__str__()` must return a string.
864
865> NOTE
866Quickest way for code changes to take effect is with `python manage.py shell` (exiting/entering).
867
868Make sure any model you define has a `__str__()` method – not only for your own convenience when using the interactive interpreter, but also because Django uses the output of `__str__()` in several places when it needs to display objects.
869
870Finally, note that `__str__()` is a good example of adding behavior to models (an ojbect displaying itself). A Django model describes the database table layout for an object, but also any functionality that object knows how to do.
871
872## Inserting and Updating Data
873Because the `Publisher` model uses an auto incrementing primary key `id`, the initial call to `save()` does one more thing: it calculates the primary key value for the record and sets it to the `id` attribute on the instance:
874```python
875>>> p.id
8763 # this will differ based on your own data
877```
878Subsequent calls to `save()` will save the record in place, without creating a new record (i.e., SQL `UPDATE` instead of `INSERT`).
879
880**Note that *all* the fields will be updated, not just the ones that have been changed.**
881
882Depending on your app, this may cause a *race condition* and you should see "Updating Multiple Objects in One Statment" below to find out how to execute this (slightly different) query (code not shown).
883
884## Selecting Objects
885*Try typing `import this` at a Python prompt.*
886
887Knowing how to create and update database records is essential, but chances are that the web applications you’ll build will be doing more querying of existing objects than creating new ones.
888
889Let's examine each part of this line:
890```python
891Publisher.objects.all()
892```
893- First, we have `Publisher` model we defined.
894- Next, we have the `ojects` attribute. This is called a *manager* (discussed in detail in Ch. 9). Managers take care of all table-level operations on data including, most important, data lookup. All models automatically get an `objects` manager; you’ll use it any time you want to look up model instances.
895- Finally, `all()`. A method on the `objects` manager that returns all the rows in the db in a *QuerySet* - an object that represents a sepectific set of rows from the db. [Appendix C for details](https://djangobook.com/generic-view-reference/)
896
897Any database lookup is going to follow this general pattern - *we'll call methods on the manager attached to the model we want to query against.*
898
899## Filtering Data
900Django provides the `filter(arg1,arg2,...)` method to translate keyword arguments into approriate SQL `WHERE` clauses. With multiple arguments, they get translated into `AND` clauses.
901
902Notice that by default the lookups use the SQL = operator to do exact match lookups. Other lookup types are available:
903```python
904>>> Publisher.objects.filter(name__contains="press")
905<QuerySet [<Publisher: Apress>]>
906```
907Like Python itself, Django uses the double underscore to signal that something “magic†is happening – here, the `__contains` part gets translated by Django into a SQL `LIKE` statement:
908```sql
909SELECT id, name, address, city, state_province, country, website
910FROM books_publisher
911WHERE name LIKE '%press%';
912```
913
914> Many other types of lookups are available, including `icontains` (case-insensitive `LIKE`), `startswith` and `endswith`, and `range` (SQL `BETWEEN` queries). [Appendix C describes all of these lookup types in detail(https://djangobook.com/generic-view-reference/).
915
916## Retrieving Single Objects
917`filter()` returns a QuerySet, which can be treated like a list. Sometimes we only want a single object, which is what the `get()` method is for.
918```python
919>>> Publisher.objects.get(name="Apress")
920<Publisher: Apress>
921```
922Since a single object is returned, a query resulting in multiple objects (or no objects) will cause an exception.
923
924The `DoesNotExist` exception is an attribute of the model’s class – `Publisher.DoesNotExist`. In your applications, you’ll want to trap these exceptions, like this:
925```python
926try:
927 p = Publisher.objects.get(name='Apress')
928except Publisher.DoesNotExist:
929 print ("Apress isn't in the database yet.")
930else:
931 print ("Apress is in the database.")
932```
933
934## Ordering Data
935**Until told**, the database will return results in a seemingly random order.
936
937In your Django applications, you’ll probably want to order your results according to a certain value – say, alphabetically. To do this, use the `order_by()` method:
938```python
939>>> Publisher.objects.order_by("name")
940<QuerySet [<Publisher: Apress>, <Publisher: GNW Independent Publishing>, <Publisher: O'Reilly>]>
941```
942Appears very similar to `all()` except the SQL generated now includes a specific ordering. You can order by any field you like:
943```
944>>> Publisher.objects.order_by("address")
945<QuerySet [<Publisher: O'Reilly>, <Publisher: GNW Independent Publishing>, <Publisher: Apress>]>
946
947>>> Publisher.objects.order_by("state_province")
948<QuerySet [<Publisher: Apress>, <Publisher: O'Reilly>, <Publisher: GNW Independent Publishing>]>
949```
950
951Use multiple arguments to further define the "tree" of the ordering:
952```
953>>> Publisher.objects.order_by("state_province", "address")
954<QuerySet [<Publisher: Apress>, <Publisher: O'Reilly>, <Publisher: GNW Independent Publishing>]>
955```
956You could reverse this ordering by prefixing the field name with a "-":
957```python
958Publisher.objects.order_by("-state_province)
959```
960
961In most cases, you'll have a particular field you usually want to order by. Django lets you specify a default ordering in the model:
962```
963class Publisher(models.Model):
964 name = models.CharField(max_length=30)
965 address = models.CharField(max_length=50)
966 city = models.CharField(max_length=60)
967 state_province = models.CharField(max_length=30)
968 country = models.CharField(max_length=50)
969 website = models.URLField()
970
971 def __str__(self):
972 return self.name
973
974 class Meta:
975 ordering = ['name']
976```
977The new concept to note here: `class Meta`, which is a class embedded within the `Publisher` class definition **(indentation matters)**.
978
979>You can use this `Meta` class on any model to specify various model-specific options. See [Appendix B](https://djangobook.com/database-api-reference/) for a full reference.
980
981**If you specifiy the ordering option**, it tells Django that unless an ordering is given explicitly with `order_by()`, **all `Publisher` objects** should be **ordered by the `name` field whenever they're retrieved with the database API.**
982
983## Chaining Lookups
984You’ve seen how you can filter data, and you’ve seen how you can order it. Often, of course, you’ll need to do both. In these cases, you simply “chain†the lookups together:
985```python
986>>> Publisher.objects.filter(country="U.S.A.").order_by("-name")
987<QuerySet [<Publisher: O'Reilly>, <Publisher: Apress>]>
988```
989This translates to an SQL query with both a `WHERE` and `ORDER BY`.
990
991## Slicing Data
992Another common need is to look up only a fixed number of rows. A Django QuerySet can be treated like a Python list, so slicing can be done similarly:
993```python
994>>> Publisher.objects.order_by('name')[0]
995<Publisher: Apress>
996```
997This translates (in SQL) roughly to:
998```sql
999SELECT id, name, address, city, state_province, country, website
1000FROM books_publisher
1001ORDER BY name
1002LIMIT 1;
1003```
1004
1005Similarly, you can retrieve a specific subset of data using Python’s range-slicing syntax:
1006```python
1007>>> Publisher.objects.order_by('name')[0:2]
1008```
1009
1010Note that negative slicing is *not* supported:
1011```python
1012>>> Publisher.objects.order_by('name')[-1]
1013Traceback (most recent call last):
1014 ...
1015AssertionError: Negative indexing is not supported.
1016```
1017This is an easy get around; just reverse the ordering instead:
1018```python
1019>>> Publisher.objects.order_by('-name')[0]
1020```
1021
1022## Updating Multiple Objects in One Statement
1023The model `save()` method updates *all* columns in a row. Suppose we only want to update the Apress `Publisher` to change the name from `'Apress'` to `'Apress Publishing'`. Using `save()`:
1024```python
1025>>> p = Publisher.objects.get(name='Apress')
1026>>> p.name = 'Apress Publishing'
1027>>> p.save()
1028```
1029Which roughly translates to the SQL:
1030```sql
1031SELECT id, name, address, city, state_province, country, website
1032FROM books_publisher
1033WHERE name = 'Apress';
1034
1035UPDATE books_publisher SET
1036 name = 'Apress Publishing',
1037 address = '2855 Telegraph Ave.',
1038 city = 'Berkeley',
1039 state_province = 'CA',
1040 country = 'U.S.A.',
1041 website = 'http://www.apress.com'
1042WHERE id = 1;
1043```
1044*Note we've assumed Apress has a publisher ID of 1.* Notice how `save()` sets *all* the column values; if you're in an environment where other columns of the database might change due to some other process, this would be **dangerous**.
1045
1046To change a *single* column, instead use the `update()` method on QuerySet objects:
1047```python
1048>>> Publisher.objects.filter(id=1).update(name='Apress Publishing')
1049```
1050The SQL translation here is much more efficient and has no chance of race conditions:
1051```sql
1052UPDATE books_publisher
1053SET name = 'Apress Publishing'
1054WHERE id = 1;
1055```
1056E.g. change the `country` from `U.S.A.` to `USA` in each `Publisher` record:
1057```python
1058>>> Publisher.objects.all().update(country='USA')
10593
1060```
1061The `update()` method has a return value – an integer representing how many records changed (hence the trailing 3).
1062
1063## Deleting Objects
1064To delete an object from your database, simply call the object’s `delete()` method:
1065```python
1066>>> p = Publisher.objects.get(name="O'Reilly")
1067>>> p.delete()
1068(1, {'books.Publisher': 1})
1069>>> Publisher.objects.all()
1070<QuerySet [<Publisher: Apress>, <Publisher: GNW Independent Publishing>]>
1071```
1072Note the return value from Django when you delete an object – Django first lists the total number of records that will be affected (in this case one) and a dictionary containing each of the models (tables) affected and how many records were deleted in each table.
1073
1074You can also delete objects in bulk by calling `delete()` on the result of any QuerySet. This is similar to the `update()` method we showed in the last section:
1075```python
1076>>> Publisher.objects.filter(country='USA').delete()
1077(1, {'books.Publisher': 1})
1078>>> Publisher.objects.all().delete()
1079(1, {'books.Publisher': 1})
1080>>> Publisher.objects.all()
1081<QuerySet []>
1082```
1083
1084**Be careful deleting data!.** As a precaution, Django requires you to explicitly use `all()` if you want to delete *everything* in your table.
1085
1086___
1087# [Chapter 5: The Django Admin Site](https://djangobook.com/django-admin-site/)
1088There’s a problem with admin interfaces, though – it’s boring to build them. Web development is fun when you’re developing public-facing functionality, but building admin interfaces is always the same. You have to authenticate users, display and handle forms, validate input, and so on. It’s boring, and it’s repetitive.
1089
1090Luckily, **Django does it all for you!**
1091
1092> In this chapter we will be exploring Django’s automatic admin interface – checking out how it provides a convenient interface to our models, and some of the other useful things we can do with it.
1093
1094## Using the Django Admin Site
1095When you run `django-admin startproject mysite`, Django creates and configures the default admin site for you. All that you need to do is create an admin user (superuser) and then you can log into the admin site.
1096
1097To create an admin user, run this command from within your virtual environment:
1098```
1099(env_mysite) :~/../.../mysite_project/mysite> python manage.py createsuperuser
1100```
1101Then follow the simple setup instructions.
1102
1103## Start the Development Server
1104```
1105(env_mysite)
1106:~/../.../mysite_project/mysite> python manage.py runserver
1107```
1108
1109View the admin site in your browser at `http://127.0.0.1:8000/admin/`. You should then be presented with a signin screen.
1110
1111## Enter the Admin Site
1112After logging in, you'll be presented with Django's admin index page.
1113
1114You should see two types of editable content: Groups and Users. They are provided by `django.contrib.auth`, the authentication framework shipped by Django. The admin site is designed to be used by nontechnical users, and as such it should be pretty self-explanatory. Either way, a brief overview:
1115* Each type of data in the Django admin site has a change list and an edit form. Change lists show you all the available objects in the database, and edit forms let you add, change or delete particular records in your database.
1116* Filtering options are at right, sorting is available by clicking a column header, and the search box at the top lets you search by username. Click the username of the user you created, and you’ll see the edit form for that user. This page lets you changes the attribures of the user.
1117* Note that the user’s password in not shown. As a security measure, Django doesn’t store raw passwords, so there is no way to retrieve a password, you have to change it.
1118* You can delete a record by clicking the delete button at the bottom left of its edit form. That’ll take you to a confirmation page, which, in some cases, will display any dependent objects that will be deleted, too. (For example, if you delete a publisher, any book with that publisher will be deleted, too!)
1119* When you edit an existing object, you’ll notice a History link in the upper-right corner of the window. Every change made through the admin interface is logged, and you can examine this log by clicking the History link.
1120
1121## How the Admin Site Works
1122When Django loads at server startup, it runs the `admin.autodiscover()` function. In earlier versions of Django, you used to call this function from `urls.py`, but now Django runs it automatically. This function iterates over your `INSTALLED_APPS` setting and looks for a file called `admin.py` in each installed app. If an `admin.py` exists in a given app, it executes the code in that file.
1123
1124The admin site will only display an edit/change interface for models that have been explicitly registered with `admin.site.register()` entered into the app’s `admin.py` file. If you were following the example, this is why the books model would not be displayed yet (to be discussed).
1125
1126The app `django.contrib.auth` includes its own `admin.py`, which is why Users and Groups showed up automatically in the admin. Other `django.contrib` apps, such as `django.contrib.redirects`, also add themselves to the admin, as do many third-party Django applications you might download from the web.
1127
1128Beyond that, the Django admin site is just a Django application, with its own models, templates, views and URLpatterns. You add it to your application by hooking it into your URLconf, just as you hook in your own views. You can inspect its templates, views and URLpatterns by poking around in `django/contrib/admin` in your copy of the Django codebase.
1129
1130# Adding Models to Django Admin
1131Let’s add our own models to the admin site, so we can add, change and delete objects in our custom database tables using this nice interface.
1132
1133Within the books directory (`mysite_project\mysite\books`), `startapp` should have created a file called `admin.py`, if not, simply create one yourself and type in the following lines of code:
1134```python
1135from django.contrib import admin
1136from .models import Publisher, Author, Book
1137
1138admin.site.register(Publisher)
1139admin.site.register(Author)
1140admin.site.register(Book)
1141```
1142
1143
1144
1145## Making Fields Optional
1146
1147
1148## Making Date and Numeric Fields Optional
1149
1150
1151## Customizing Field Labels
1152
1153
1154## Custom ModelAdmin classes
1155
1156
1157
1158# Customizing Change Lists and Forms
1159
1160
1161## Customizing Edit Forms
1162
1163
1164
1165# Users, Groups, and Permissions
1166
1167
1168## When and Why to Use the Admin Interface - And When Not to
1169
1170
1171___
1172# [Chapter 6: Django Forms](https://djangobook.com/django-forms/)
1173
1174## Getting Dta from the Request Object
1175
1176
1177## Information About the URL
1178
1179
1180## Other Information About the Request
1181
1182
1183## Information About Submitted Data
1184
1185
1186## A Simple Django Form-Handling Example
1187
1188
1189## Query String Parameters
1190
1191
1192## Improving Our Simple Form-Handling Example
1193
1194
1195
1196# Django Form Validation
1197## Simple Validation
1198
1199
1200## Making a Contact Form
1201
1202
1203## Your First Form Class
1204
1205
1206
1207# Tying Forms to Views
1208
1209
1210## Changing How Fields Are Rendered
1211
1212
1213## Setting a Maximum Length
1214
1215
1216## Setting Initial Values
1217
1218
1219## Custom Validation Rules
1220
1221
1222## Specifying labels
1223
1224
1225## Customizing Form Design
1226
1227___
1228
1229
1230
1231
1232___
1233> All information above should be credited to [The Django Book](https://djangobook.com). I, Jack Kasbeer, am the author of this document, but it's creation have been purely educational and I do not take any credit for most of the wording as it's largely copy/pasted.
1234> [git](httsp://github.com/jcksber)
1235> [insta](https://insagram.com/overprivelegd)
1236> [business card](https://jackkasbeer.co)
1237> [soundccloud](https://soundcloud.com/kamikaze-kaze)