...
.. nextslide:: Request Context Revisited
When we set up our views, we used the ``render`` shortcut, which provides a
``RequestContext``
.. rst-class:: build
.. container::
This gives us access to ``user`` in our templates
It provides access to methods about the state and rights of that user
We can use these to conditionally display links or UI elements. Like only
showing the admin link to staff members.
.. nextslide:: Login/Logout
Django also provides a reasonable set of views for login/logout.
.. rst-class:: build
.. container::
The first step to using them is to hook them into a urlconf.
.. container::
Add the following to ``mysite/urls.py``:
.. code-block:: python
# add an import at the top
from django.contrib.auth.views import login, logout
# and update the list of urlconfs
url(r'^', include('myblog.urls')), #<- already there
url(r'^login/$',
login,
{'template_name': 'login.html'},
name="login"),
url(r'^logout/$',
logout,
{'next_page': '/'},
name="logout"),
.. nextslide:: Login Template
We need to create a new ``login.html`` template in ``mysite/templates``:
.. code-block:: jinja
{% extends "base.html" %}
{% block content %}
My Blog Login
{% endblock %}
.. nextslide:: Submitting Forms
In a web application, submitting forms is potentially hazardous
.. rst-class:: build
.. container::
Data is being sent to our application from some remote place
If that data is going to alter the state of our application, we **must**
use POST
Even so, we are vulnerable to Cross-Site Request Forgery, a common attack
vector.
.. nextslide:: Danger: CSRF
Django provides a convenient system to fight this.
.. rst-class:: build
.. container::
In fact, for POST requests, it *requires* that you use it.
The Django middleware that does this is enabled by default.
All you need to do is include the ``{% csrf_token %}`` tag in your form.
.. nextslide:: Hooking It Up
In ``base.html`` make the following updates:
.. rst-class:: build
.. container::
.. code-block:: jinja
admin
logout
login
.. container::
Finally, in ``settings.py`` add the following:
.. code-block:: python
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/'
.. nextslide:: Forms In Django
In adding a login view, we've gotten a sneak peak at how forms work in Django.
.. rst-class:: build
.. container::
However, learning more about them is beyond what we can achieve in this
session.
The form system in Django is quite nice, however. I urge you to
`read more about it`_
In particular, you might want to pay attention to the documentation on
`Model Forms`_
.. _read more about it: https://docs.djangoproject.com/en/1.6/topics/forms/
.. _Model Forms: https://docs.djangoproject.com/en/1.6/topics/forms/modelforms/
Ta-Daaaaaa!
-----------
So, that's it. We've created a workable, simple blog app in Django.
.. rst-class:: build
.. container::
If you fell behind at some point, the app as it now stands is in our class
resources as ``mysite_stage_3``.
There's much more we could do with this app. And for homework, you'll do
some of it.
Then next session, we'll work together as pairs to implement a simple
feature to extend the blog
Homework
========
.. rst-class:: left
For your homework this week, we'll fix one glaring problem with our blog admin.
.. rst-class:: build left
.. container::
As you created new categories and posts, and related them to each-other,
how did you feel about that work?
Although from a data perspective, the category model is the right place for
the ManytoMany relationship to posts, this leads to awkward usage in the
admin.
It would be much easier if we could designate a category for a post *from
the Post admin*.
Your Assignment
---------------
You'll be reversing that relationship so that you can only add categories to
posts
.. rst-class:: build
.. container::
Take the following steps:
1. Read the documentation about the `Django admin.`_
2. You'll need to create a customized `ModelAdmin`_ class for the ``Post``
and ``Category`` models.
3. And you'll need to create an `InlineModelAdmin`_ to represent Categories
on the Post admin view.
4. Finally, you'll need to `exclude`_ the 'posts' field from the form in
your ``Category`` admin.
.. _Django admin.: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/
.. _ModelAdmin: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#modeladmin-objects
.. _InlineModelAdmin: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#inlinemodeladmin-objects
.. _exclude: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#django.contrib.admin.ModelAdmin.exclude
.. nextslide:: Pushing Further
All told, those changes should not require more than about 15 total lines of
code.
.. rst-class:: build
.. container::
The trick of course is reading and finding out which fifteen lines to
write.
If you complete that task in less than 3-4 hours of work, consider looking
into other ways of customizing the admin.
.. nextslide:: Tasks you might consider
.. rst-class:: build
* Change the admin index to say 'Categories' instead of 'Categorys'. (hint, the
way to change this has nothing to do with the admin)
* Add columns for the date fields to the list display of Posts.
* Display the created and modified dates for your posts when viewing them in
the admin.
* Add a column to the list display of Posts that shows the author. For more
fun, make this a link that takes you to the admin page for that user.
* For the biggest challenge, look into `admin actions`_ and add an action to
the Post admin that allows you to publish posts in bulk from the Post list
display
.. _admin actions: https://docs.djangoproject.com/en/1.6/ref/contrib/admin/actions/