| 1 |
============================= |
|---|
| 2 |
User authentication in Django |
|---|
| 3 |
============================= |
|---|
| 4 |
|
|---|
| 5 |
Django comes with a user authentication system. It handles user accounts, |
|---|
| 6 |
groups, permissions and cookie-based user sessions. This document explains how |
|---|
| 7 |
things work. |
|---|
| 8 |
|
|---|
| 9 |
Overview |
|---|
| 10 |
======== |
|---|
| 11 |
|
|---|
| 12 |
The auth system consists of: |
|---|
| 13 |
|
|---|
| 14 |
* Users |
|---|
| 15 |
* Permissions: Binary (yes/no) flags designating whether a user may perform |
|---|
| 16 |
a certain task. |
|---|
| 17 |
* Groups: A generic way of applying labels and permissions to more than one |
|---|
| 18 |
user. |
|---|
| 19 |
* Messages: A simple way to queue messages for given users. |
|---|
| 20 |
|
|---|
| 21 |
Installation |
|---|
| 22 |
============ |
|---|
| 23 |
|
|---|
| 24 |
Authentication support is bundled as a Django application in |
|---|
| 25 |
``django.contrib.auth``. To install it, do the following: |
|---|
| 26 |
|
|---|
| 27 |
1. Put ``'django.contrib.auth'`` in your ``INSTALLED_APPS`` setting. |
|---|
| 28 |
2. Run the command ``manage.py syncdb``. |
|---|
| 29 |
|
|---|
| 30 |
Note that the default ``settings.py`` file created by |
|---|
| 31 |
``django-admin.py startproject`` includes ``'django.contrib.auth'`` in |
|---|
| 32 |
``INSTALLED_APPS`` for convenience. If your ``INSTALLED_APPS`` already contains |
|---|
| 33 |
``'django.contrib.auth'``, feel free to run ``manage.py syncdb`` again; you |
|---|
| 34 |
can run that command as many times as you'd like, and each time it'll only |
|---|
| 35 |
install what's needed. |
|---|
| 36 |
|
|---|
| 37 |
The ``syncdb`` command creates the necessary database tables, creates |
|---|
| 38 |
permission objects for all installed apps that need 'em, and prompts you to |
|---|
| 39 |
create a superuser account the first time you run it. |
|---|
| 40 |
|
|---|
| 41 |
Once you've taken those steps, that's it. |
|---|
| 42 |
|
|---|
| 43 |
Users |
|---|
| 44 |
===== |
|---|
| 45 |
|
|---|
| 46 |
Users are represented by a standard Django model, which lives in |
|---|
| 47 |
`django/contrib/auth/models.py`_. |
|---|
| 48 |
|
|---|
| 49 |
.. _django/contrib/auth/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py |
|---|
| 50 |
|
|---|
| 51 |
API reference |
|---|
| 52 |
------------- |
|---|
| 53 |
|
|---|
| 54 |
Fields |
|---|
| 55 |
~~~~~~ |
|---|
| 56 |
|
|---|
| 57 |
``User`` objects have the following fields: |
|---|
| 58 |
|
|---|
| 59 |
* ``username`` -- Required. 30 characters or fewer. Alphanumeric characters |
|---|
| 60 |
only (letters, digits and underscores). |
|---|
| 61 |
* ``first_name`` -- Optional. 30 characters or fewer. |
|---|
| 62 |
* ``last_name`` -- Optional. 30 characters or fewer. |
|---|
| 63 |
* ``email`` -- Optional. E-mail address. |
|---|
| 64 |
* ``password`` -- Required. A hash of, and metadata about, the password. |
|---|
| 65 |
(Django doesn't store the raw password.) Raw passwords can be arbitrarily |
|---|
| 66 |
long and can contain any character. See the "Passwords" section below. |
|---|
| 67 |
* ``is_staff`` -- Boolean. Designates whether this user can access the |
|---|
| 68 |
admin site. |
|---|
| 69 |
* ``is_active`` -- Boolean. Designates whether this account can be used |
|---|
| 70 |
to log in. Set this flag to ``False`` instead of deleting accounts. |
|---|
| 71 |
* ``is_superuser`` -- Boolean. Designates that this user has all permissions |
|---|
| 72 |
without explicitly assigning them. |
|---|
| 73 |
* ``last_login`` -- A datetime of the user's last login. Is set to the |
|---|
| 74 |
current date/time by default. |
|---|
| 75 |
* ``date_joined`` -- A datetime designating when the account was created. |
|---|
| 76 |
Is set to the current date/time by default when the account is created. |
|---|
| 77 |
|
|---|
| 78 |
Methods |
|---|
| 79 |
~~~~~~~ |
|---|
| 80 |
|
|---|
| 81 |
``User`` objects have two many-to-many fields: ``groups`` and |
|---|
| 82 |
``user_permissions``. ``User`` objects can access their related |
|---|
| 83 |
objects in the same way as any other `Django model`_:: |
|---|
| 84 |
|
|---|
| 85 |
myuser.groups = [group_list] |
|---|
| 86 |
myuser.groups.add(group, group,...) |
|---|
| 87 |
myuser.groups.remove(group, group,...) |
|---|
| 88 |
myuser.groups.clear() |
|---|
| 89 |
myuser.permissions = [permission_list] |
|---|
| 90 |
myuser.permissions.add(permission, permission, ...) |
|---|
| 91 |
myuser.permissions.remove(permission, permission, ...] |
|---|
| 92 |
myuser.permissions.clear() |
|---|
| 93 |
|
|---|
| 94 |
In addition to those automatic API methods, ``User`` objects have the following |
|---|
| 95 |
custom methods: |
|---|
| 96 |
|
|---|
| 97 |
* ``is_anonymous()`` -- Always returns ``False``. This is a way of |
|---|
| 98 |
differentiating ``User`` and ``AnonymousUser`` objects. Generally, you |
|---|
| 99 |
should prefer using ``is_authenticated()`` to this method. |
|---|
| 100 |
|
|---|
| 101 |
* ``is_authenticated()`` -- Always returns ``True``. This is a way to |
|---|
| 102 |
tell if the user has been authenticated. This does not imply any |
|---|
| 103 |
permissions, and doesn't check if the user is active - it only indicates |
|---|
| 104 |
that the user has provided a valid username and password. |
|---|
| 105 |
|
|---|
| 106 |
* ``get_full_name()`` -- Returns the ``first_name`` plus the ``last_name``, |
|---|
| 107 |
with a space in between. |
|---|
| 108 |
|
|---|
| 109 |
* ``set_password(raw_password)`` -- Sets the user's password to the given |
|---|
| 110 |
raw string, taking care of the password hashing. Doesn't save the |
|---|
| 111 |
``User`` object. |
|---|
| 112 |
|
|---|
| 113 |
* ``check_password(raw_password)`` -- Returns ``True`` if the given raw |
|---|
| 114 |
string is the correct password for the user. (This takes care of the |
|---|
| 115 |
password hashing in making the comparison.) |
|---|
| 116 |
|
|---|
| 117 |
* ``get_group_permissions()`` -- Returns a list of permission strings that |
|---|
| 118 |
the user has, through his/her groups. |
|---|
| 119 |
|
|---|
| 120 |
* ``get_all_permissions()`` -- Returns a list of permission strings that |
|---|
| 121 |
the user has, both through group and user permissions. |
|---|
| 122 |
|
|---|
| 123 |
* ``has_perm(perm)`` -- Returns ``True`` if the user has the specified |
|---|
| 124 |
permission, where perm is in the format ``"package.codename"``. |
|---|
| 125 |
If the user is inactive, this method will always return ``False``. |
|---|
| 126 |
|
|---|
| 127 |
* ``has_perms(perm_list)`` -- Returns ``True`` if the user has each of the |
|---|
| 128 |
specified permissions, where each perm is in the format |
|---|
| 129 |
``"package.codename"``. If the user is inactive, this method will |
|---|
| 130 |
always return ``False``. |
|---|
| 131 |
|
|---|
| 132 |
* ``has_module_perms(package_name)`` -- Returns ``True`` if the user has |
|---|
| 133 |
any permissions in the given package (the Django app label). |
|---|
| 134 |
If the user is inactive, this method will always return ``False``. |
|---|
| 135 |
|
|---|
| 136 |
* ``get_and_delete_messages()`` -- Returns a list of ``Message`` objects in |
|---|
| 137 |
the user's queue and deletes the messages from the queue. |
|---|
| 138 |
|
|---|
| 139 |
* ``email_user(subject, message, from_email=None)`` -- Sends an e-mail to |
|---|
| 140 |
the user. If ``from_email`` is ``None``, Django uses the |
|---|
| 141 |
`DEFAULT_FROM_EMAIL`_ setting. |
|---|
| 142 |
|
|---|
| 143 |
* ``get_profile()`` -- Returns a site-specific profile for this user. |
|---|
| 144 |
Raises ``django.contrib.auth.models.SiteProfileNotAvailable`` if the current site |
|---|
| 145 |
doesn't allow profiles. |
|---|
| 146 |
|
|---|
| 147 |
.. _Django model: ../model_api/ |
|---|
| 148 |
.. _DEFAULT_FROM_EMAIL: ../settings/#default-from-email |
|---|
| 149 |
|
|---|
| 150 |
Manager functions |
|---|
| 151 |
~~~~~~~~~~~~~~~~~ |
|---|
| 152 |
|
|---|
| 153 |
The ``User`` model has a custom manager that has the following helper functions: |
|---|
| 154 |
|
|---|
| 155 |
* ``create_user(username, email, password)`` -- Creates, saves and returns |
|---|
| 156 |
a ``User``. The ``username``, ``email`` and ``password`` are set as |
|---|
| 157 |
given, and the ``User`` gets ``is_active=True``. |
|---|
| 158 |
|
|---|
| 159 |
See _`Creating users` for example usage. |
|---|
| 160 |
|
|---|
| 161 |
* ``make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')`` |
|---|
| 162 |
Returns a random password with the given length and given string of |
|---|
| 163 |
allowed characters. (Note that the default value of ``allowed_chars`` |
|---|
| 164 |
doesn't contain ``"I"`` or letters that look like it, to avoid user |
|---|
| 165 |
confusion. |
|---|
| 166 |
|
|---|
| 167 |
Basic usage |
|---|
| 168 |
----------- |
|---|
| 169 |
|
|---|
| 170 |
Creating users |
|---|
| 171 |
~~~~~~~~~~~~~~ |
|---|
| 172 |
|
|---|
| 173 |
The most basic way to create users is to use the ``create_user`` helper |
|---|
| 174 |
function that comes with Django:: |
|---|
| 175 |
|
|---|
| 176 |
>>> from django.contrib.auth.models import User |
|---|
| 177 |
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword') |
|---|
| 178 |
|
|---|
| 179 |
# At this point, user is a User object ready to be saved |
|---|
| 180 |
# to the database. You can continue to change its attributes |
|---|
| 181 |
# if you want to change other fields. |
|---|
| 182 |
>>> user.is_staff = True |
|---|
| 183 |
>>> user.save() |
|---|
| 184 |
|
|---|
| 185 |
Changing passwords |
|---|
| 186 |
~~~~~~~~~~~~~~~~~~ |
|---|
| 187 |
|
|---|
| 188 |
Change a password with ``set_password()``:: |
|---|
| 189 |
|
|---|
| 190 |
>>> from django.contrib.auth.models import User |
|---|
| 191 |
>>> u = User.objects.get(username__exact='john') |
|---|
| 192 |
>>> u.set_password('new password') |
|---|
| 193 |
>>> u.save() |
|---|
| 194 |
|
|---|
| 195 |
Don't set the ``password`` attribute directly unless you know what you're |
|---|
| 196 |
doing. This is explained in the next section. |
|---|
| 197 |
|
|---|
| 198 |
Passwords |
|---|
| 199 |
--------- |
|---|
| 200 |
|
|---|
| 201 |
The ``password`` attribute of a ``User`` object is a string in this format:: |
|---|
| 202 |
|
|---|
| 203 |
hashtype$salt$hash |
|---|
| 204 |
|
|---|
| 205 |
That's hashtype, salt and hash, separated by the dollar-sign character. |
|---|
| 206 |
|
|---|
| 207 |
Hashtype is either ``sha1`` (default) or ``md5`` -- the algorithm used to |
|---|
| 208 |
perform a one-way hash of the password. Salt is a random string used to salt |
|---|
| 209 |
the raw password to create the hash. |
|---|
| 210 |
|
|---|
| 211 |
For example:: |
|---|
| 212 |
|
|---|
| 213 |
sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4 |
|---|
| 214 |
|
|---|
| 215 |
The ``User.set_password()`` and ``User.check_password()`` functions handle |
|---|
| 216 |
the setting and checking of these values behind the scenes. |
|---|
| 217 |
|
|---|
| 218 |
Previous Django versions, such as 0.90, used simple MD5 hashes without password |
|---|
| 219 |
salts. For backwards compatibility, those are still supported; they'll be |
|---|
| 220 |
converted automatically to the new style the first time ``check_password()`` |
|---|
| 221 |
works correctly for a given user. |
|---|
| 222 |
|
|---|
| 223 |
Anonymous users |
|---|
| 224 |
--------------- |
|---|
| 225 |
|
|---|
| 226 |
``django.contrib.auth.models.AnonymousUser`` is a class that implements |
|---|
| 227 |
the ``django.contrib.auth.models.User`` interface, with these differences: |
|---|
| 228 |
|
|---|
| 229 |
* ``id`` is always ``None``. |
|---|
| 230 |
* ``is_anonymous()`` returns ``True`` instead of ``False``. |
|---|
| 231 |
* ``is_authenticated()`` returns ``False`` instead of ``True``. |
|---|
| 232 |
* ``has_perm()`` always returns ``False``. |
|---|
| 233 |
* ``set_password()``, ``check_password()``, ``save()``, ``delete()``, |
|---|
| 234 |
``set_groups()`` and ``set_permissions()`` raise ``NotImplementedError``. |
|---|
| 235 |
|
|---|
| 236 |
In practice, you probably won't need to use ``AnonymousUser`` objects on your |
|---|
| 237 |
own, but they're used by Web requests, as explained in the next section. |
|---|
| 238 |
|
|---|
| 239 |
Creating superusers |
|---|
| 240 |
------------------- |
|---|
| 241 |
|
|---|
| 242 |
``manage.py syncdb`` prompts you to create a superuser the first time you run |
|---|
| 243 |
it after adding ``'django.contrib.auth'`` to your ``INSTALLED_APPS``. But if |
|---|
| 244 |
you need to create a superuser after that via the command line, you can use the |
|---|
| 245 |
``create_superuser.py`` utility. Just run this command:: |
|---|
| 246 |
|
|---|
| 247 |
python /path/to/django/contrib/auth/create_superuser.py |
|---|
| 248 |
|
|---|
| 249 |
Make sure to substitute ``/path/to/`` with the path to the Django codebase on |
|---|
| 250 |
your filesystem. |
|---|
| 251 |
|
|---|
| 252 |
Authentication in Web requests |
|---|
| 253 |
============================== |
|---|
| 254 |
|
|---|
| 255 |
Until now, this document has dealt with the low-level APIs for manipulating |
|---|
| 256 |
authentication-related objects. On a higher level, Django can hook this |
|---|
| 257 |
authentication framework into its system of `request objects`_. |
|---|
| 258 |
|
|---|
| 259 |
First, install the ``SessionMiddleware`` and ``AuthenticationMiddleware`` |
|---|
| 260 |
middlewares by adding them to your ``MIDDLEWARE_CLASSES`` setting. See the |
|---|
| 261 |
`session documentation`_ for more information. |
|---|
| 262 |
|
|---|
| 263 |
Once you have those middlewares installed, you'll be able to access |
|---|
| 264 |
``request.user`` in views. ``request.user`` will give you a ``User`` object |
|---|
| 265 |
representing the currently logged-in user. If a user isn't currently logged in, |
|---|
| 266 |
``request.user`` will be set to an instance of ``AnonymousUser`` (see the |
|---|
| 267 |
previous section). You can tell them apart with ``is_authenticated()``, like so:: |
|---|
| 268 |
|
|---|
| 269 |
if request.user.is_authenticated(): |
|---|
| 270 |
# Do something for authenticated users. |
|---|
| 271 |
else: |
|---|
| 272 |
# Do something for anonymous users. |
|---|
| 273 |
|
|---|
| 274 |
.. _request objects: ../request_response/#httprequest-objects |
|---|
| 275 |
.. _session documentation: ../sessions/ |
|---|
| 276 |
|
|---|
| 277 |
How to log a user in |
|---|
| 278 |
-------------------- |
|---|
| 279 |
|
|---|
| 280 |
Django provides two functions in ``django.contrib.auth``: ``authenticate()`` |
|---|
| 281 |
and ``login()``. |
|---|
| 282 |
|
|---|
| 283 |
To authenticate a given username and password, use ``authenticate()``. It |
|---|
| 284 |
takes two keyword arguments, ``username`` and ``password``, and it returns |
|---|
| 285 |
a ``User`` object if the password is valid for the given username. If the |
|---|
| 286 |
password is invalid, ``authenticate()`` returns ``None``. Example:: |
|---|
| 287 |
|
|---|
| 288 |
from django.contrib.auth import authenticate |
|---|
| 289 |
user = authenticate(username='john', password='secret') |
|---|
| 290 |
if user is not None: |
|---|
| 291 |
if user.is_active: |
|---|
| 292 |
print "You provided a correct username and password!" |
|---|
| 293 |
else: |
|---|
| 294 |
print "Your account has been disabled!" |
|---|
| 295 |
else: |
|---|
| 296 |
print "Your username and password were incorrect." |
|---|
| 297 |
|
|---|
| 298 |
To log a user in, in a view, use ``login()``. It takes an ``HttpRequest`` |
|---|
| 299 |
object and a ``User`` object. ``login()`` saves the user's ID in the session, |
|---|
| 300 |
using Django's session framework, so, as mentioned above, you'll need to make |
|---|
| 301 |
sure to have the session middleware installed. |
|---|
| 302 |
|
|---|
| 303 |
This example shows how you might use both ``authenticate()`` and ``login()``:: |
|---|
| 304 |
|
|---|
| 305 |
from django.contrib.auth import authenticate, login |
|---|
| 306 |
|
|---|
| 307 |
def my_view(request): |
|---|
| 308 |
username = request.POST['username'] |
|---|
| 309 |
password = request.POST['password'] |
|---|
| 310 |
user = authenticate(username=username, password=password) |
|---|
| 311 |
if user is not None: |
|---|
| 312 |
if user.is_active: |
|---|
| 313 |
login(request, user) |
|---|
| 314 |
# Redirect to a success page. |
|---|
| 315 |
else: |
|---|
| 316 |
# Return a 'disabled account' error message |
|---|
| 317 |
else: |
|---|
| 318 |
# Return an 'invalid login' error message. |
|---|
| 319 |
|
|---|
| 320 |
How to log a user out |
|---|
| 321 |
--------------------- |
|---|
| 322 |
|
|---|
| 323 |
To log out a user who has been logged in via ``django.contrib.auth.login()``, |
|---|
| 324 |
use ``django.contrib.auth.logout()`` within your view. It takes an |
|---|
| 325 |
``HttpRequest`` object and has no return value. Example:: |
|---|
| 326 |
|
|---|
| 327 |
from django.contrib.auth import logout |
|---|
| 328 |
|
|---|
| 329 |
def logout_view(request): |
|---|
| 330 |
logout(request) |
|---|
| 331 |
# Redirect to a success page. |
|---|
| 332 |
|
|---|
| 333 |
Note that ``logout()`` doesn't throw any errors if the user wasn't logged in. |
|---|
| 334 |
|
|---|
| 335 |
Limiting access to logged-in users |
|---|
| 336 |
---------------------------------- |
|---|
| 337 |
|
|---|
| 338 |
The raw way |
|---|
| 339 |
~~~~~~~~~~~ |
|---|
| 340 |
|
|---|
| 341 |
The simple, raw way to limit access to pages is to check |
|---|
| 342 |
``request.user.is_authenticated()`` and either redirect to a login page:: |
|---|
| 343 |
|
|---|
| 344 |
from django.http import HttpResponseRedirect |
|---|
| 345 |
|
|---|
| 346 |
def my_view(request): |
|---|
| 347 |
if not request.user.is_authenticated(): |
|---|
| 348 |
return HttpResponseRedirect('/login/?next=%s' % request.path) |
|---|
| 349 |
# ... |
|---|
| 350 |
|
|---|
| 351 |
...or display an error message:: |
|---|
| 352 |
|
|---|
| 353 |
def my_view(request): |
|---|
| 354 |
if not request.user.is_authenticated(): |
|---|
| 355 |
return render_to_response('myapp/login_error.html') |
|---|
| 356 |
# ... |
|---|
| 357 |
|
|---|
| 358 |
The login_required decorator |
|---|
| 359 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 360 |
|
|---|
| 361 |
As a shortcut, you can use the convenient ``login_required`` decorator:: |
|---|
| 362 |
|
|---|
| 363 |
from django.contrib.auth.decorators import login_required |
|---|
| 364 |
|
|---|
| 365 |
def my_view(request): |
|---|
| 366 |
# ... |
|---|
| 367 |
my_view = login_required(my_view) |
|---|
| 368 |
|
|---|
| 369 |
Here's an equivalent example, using the more compact decorator syntax |
|---|
| 370 |
introduced in Python 2.4:: |
|---|
| 371 |
|
|---|
| 372 |
from django.contrib.auth.decorators import login_required |
|---|
| 373 |
|
|---|
| 374 |
@login_required |
|---|
| 375 |
def my_view(request): |
|---|
| 376 |
# ... |
|---|
| 377 |
|
|---|
| 378 |
``login_required`` does the following: |
|---|
| 379 |
|
|---|
| 380 |
* If the user isn't logged in, redirect to ``/accounts/login/``, passing |
|---|
| 381 |
the current absolute URL in the query string as ``next``. For example: |
|---|
| 382 |
``/accounts/login/?next=/polls/3/``. |
|---|
| 383 |
* If the user is logged in, execute the view normally. The view code is |
|---|
| 384 |
free to assume the user is logged in. |
|---|
| 385 |
|
|---|
| 386 |
Note that you'll need to map the appropriate Django view to ``/accounts/login/``. |
|---|
| 387 |
To do this, add the following line to your URLconf:: |
|---|
| 388 |
|
|---|
| 389 |
(r'^accounts/login/$', 'django.contrib.auth.views.login'), |
|---|
| 390 |
|
|---|
| 391 |
Here's what ``django.contrib.auth.views.login`` does:: |
|---|
| 392 |
|
|---|
| 393 |
* If called via ``GET``, it displays a login form that POSTs to the same |
|---|
| 394 |
URL. More on this in a bit. |
|---|
| 395 |
|
|---|
| 396 |
* If called via ``POST``, it tries to log the user in. If login is |
|---|
| 397 |
successful, the view redirects to the URL specified in ``next``. If |
|---|
| 398 |
``next`` isn't provided, it redirects to ``/accounts/profile/`` (which is |
|---|
| 399 |
currently hard-coded). If login isn't successful, it redisplays the login |
|---|
| 400 |
form. |
|---|
| 401 |
|
|---|
| 402 |
It's your responsibility to provide the login form in a template called |
|---|
| 403 |
``registration/login.html`` by default. This template gets passed three |
|---|
| 404 |
template context variables: |
|---|
| 405 |
|
|---|
| 406 |
* ``form``: A ``FormWrapper`` object representing the login form. See the |
|---|
| 407 |
`forms documentation`_ for more on ``FormWrapper`` objects. |
|---|
| 408 |
* ``next``: The URL to redirect to after successful login. This may contain |
|---|
| 409 |
a query string, too. |
|---|
| 410 |
* ``site_name``: The name of the current ``Site``, according to the |
|---|
| 411 |
``SITE_ID`` setting. See the `site framework docs`_. |
|---|
| 412 |
|
|---|
| 413 |
If you'd prefer not to call the template ``registration/login.html``, you can |
|---|
| 414 |
pass the ``template_name`` parameter via the extra arguments to the view in |
|---|
| 415 |
your URLconf. For example, this URLconf line would use ``myapp/login.html`` |
|---|
| 416 |
instead:: |
|---|
| 417 |
|
|---|
| 418 |
(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}), |
|---|
| 419 |
|
|---|
| 420 |
Here's a sample ``registration/login.html`` template you can use as a starting |
|---|
| 421 |
point. It assumes you have a ``base.html`` template that defines a ``content`` |
|---|
| 422 |
block:: |
|---|
| 423 |
|
|---|
| 424 |
{% extends "base.html" %} |
|---|
| 425 |
|
|---|
| 426 |
{% block content %} |
|---|
| 427 |
|
|---|
| 428 |
{% if form.has_errors %} |
|---|
| 429 |
<p>Your username and password didn't match. Please try again.</p> |
|---|
| 430 |
{% endif %} |
|---|
| 431 |
|
|---|
| 432 |
<form method="post" action="."> |
|---|
| 433 |
<table> |
|---|
| 434 |
<tr><td><label for="id_username">Username:</label></td><td>{{ form.username }}</td></tr> |
|---|
| 435 |
<tr><td><label for="id_password">Password:</label></td><td>{{ form.password }}</td></tr> |
|---|
| 436 |
</table> |
|---|
| 437 |
|
|---|
| 438 |
<input type="submit" value="login" /> |
|---|
| 439 |
<input type="hidden" name="next" value="{{ next }}" /> |
|---|
| 440 |
</form> |
|---|
| 441 |
|
|---|
| 442 |
{% endblock %} |
|---|
| 443 |
|
|---|
| 444 |
.. _forms documentation: ../forms/ |
|---|
| 445 |
.. _site framework docs: ../sites/ |
|---|
| 446 |
|
|---|
| 447 |
Limiting access to logged-in users that pass a test |
|---|
| 448 |
--------------------------------------------------- |
|---|
| 449 |
|
|---|
| 450 |
To limit access based on certain permissions or some other test, you'd do |
|---|
| 451 |
essentially the same thing as described in the previous section. |
|---|
| 452 |
|
|---|
| 453 |
The simple way is to run your test on ``request.user`` in the view directly. |
|---|
| 454 |
For example, this view checks to make sure the user is logged in and has the |
|---|
| 455 |
permission ``polls.can_vote``:: |
|---|
| 456 |
|
|---|
| 457 |
def my_view(request): |
|---|
| 458 |
if not (request.user.is_authenticated() and request.user.has_perm('polls.can_vote')): |
|---|
| 459 |
return HttpResponse("You can't vote in this poll.") |
|---|
| 460 |
# ... |
|---|
| 461 |
|
|---|
| 462 |
As a shortcut, you can use the convenient ``user_passes_test`` decorator:: |
|---|
| 463 |
|
|---|
| 464 |
from django.contrib.auth.decorators import user_passes_test |
|---|
| 465 |
|
|---|
| 466 |
def my_view(request): |
|---|
| 467 |
# ... |
|---|
| 468 |
my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'))(my_view) |
|---|
| 469 |
|
|---|
| 470 |
We're using this particular test as a relatively simple example. However, if |
|---|
| 471 |
you just want to test whether a permission is available to a user, you can use |
|---|
| 472 |
the ``permission_required()`` decorator, described later in this document. |
|---|
| 473 |
|
|---|
| 474 |
Here's the same thing, using Python 2.4's decorator syntax:: |
|---|
| 475 |
|
|---|
| 476 |
from django.contrib.auth.decorators import user_passes_test |
|---|
| 477 |
|
|---|
| 478 |
@user_passes_test(lambda u: u.has_perm('polls.can_vote')) |
|---|
| 479 |
def my_view(request): |
|---|
| 480 |
# ... |
|---|
| 481 |
|
|---|
| 482 |
``user_passes_test`` takes a required argument: a callable that takes a |
|---|
| 483 |
``User`` object and returns ``True`` if the user is allowed to view the page. |
|---|
| 484 |
Note that ``user_passes_test`` does not automatically check that the ``User`` |
|---|
| 485 |
is not anonymous. |
|---|
| 486 |
|
|---|
| 487 |
``user_passes_test()`` takes an optional ``login_url`` argument, which lets you |
|---|
| 488 |
specify the URL for your login page (``/accounts/login/`` by default). |
|---|
| 489 |
|
|---|
| 490 |
Example in Python 2.3 syntax:: |
|---|
| 491 |
|
|---|
| 492 |
from django.contrib.auth.decorators import user_passes_test |
|---|
| 493 |
|
|---|
| 494 |
def my_view(request): |
|---|
| 495 |
# ... |
|---|
| 496 |
my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')(my_view) |
|---|
| 497 |
|
|---|
| 498 |
Example in Python 2.4 syntax:: |
|---|
| 499 |
|
|---|
| 500 |
from django.contrib.auth.decorators import user_passes_test |
|---|
| 501 |
|
|---|
| 502 |
@user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/') |
|---|
| 503 |
def my_view(request): |
|---|
| 504 |
# ... |
|---|
| 505 |
|
|---|
| 506 |
The permission_required decorator |
|---|
| 507 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 508 |
|
|---|
| 509 |
**New in Django development version** |
|---|
| 510 |
|
|---|
| 511 |
It's a relatively common task to check whether a user has a particular |
|---|
| 512 |
permission. For that reason, Django provides a shortcut for that case: the |
|---|
| 513 |
``permission_required()`` decorator. Using this decorator, the earlier example |
|---|
| 514 |
can be written as:: |
|---|
| 515 |
|
|---|
| 516 |
from django.contrib.auth.decorators import permission_required |
|---|
| 517 |
|
|---|
| 518 |
def my_view(request): |
|---|
| 519 |
# ... |
|---|
| 520 |
my_view = permission_required('polls.can_vote')(my_view) |
|---|
| 521 |
|
|---|
| 522 |
Note that ``permission_required()`` also takes an optional ``login_url`` |
|---|
| 523 |
parameter. Example:: |
|---|
| 524 |
|
|---|
| 525 |
from django.contrib.auth.decorators import permission_required |
|---|
| 526 |
|
|---|
| 527 |
def my_view(request): |
|---|
| 528 |
# ... |
|---|
| 529 |
my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view) |
|---|
| 530 |
|
|---|
| 531 |
As in the ``login_required`` decorator, ``login_url`` defaults to |
|---|
| 532 |
``'/accounts/login/'``. |
|---|
| 533 |
|
|---|
| 534 |
Limiting access to generic views |
|---|
| 535 |
-------------------------------- |
|---|
| 536 |
|
|---|
| 537 |
To limit access to a `generic view`_, write a thin wrapper around the view, |
|---|
| 538 |
and point your URLconf to your wrapper instead of the generic view itself. |
|---|
| 539 |
For example:: |
|---|
| 540 |
|
|---|
| 541 |
from django.views.generic.date_based import object_detail |
|---|
| 542 |
|
|---|
| 543 |
@login_required |
|---|
| 544 |
def limited_object_detail(*args, **kwargs): |
|---|
| 545 |
return object_detail(*args, **kwargs) |
|---|
| 546 |
|
|---|
| 547 |
.. _generic view: ../generic_views/ |
|---|
| 548 |
|
|---|
| 549 |
Permissions |
|---|
| 550 |
=========== |
|---|
| 551 |
|
|---|
| 552 |
Django comes with a simple permissions system. It provides a way to assign |
|---|
| 553 |
permissions to specific users and groups of users. |
|---|
| 554 |
|
|---|
| 555 |
It's used by the Django admin site, but you're welcome to use it in your own |
|---|
| 556 |
code. |
|---|
| 557 |
|
|---|
| 558 |
The Django admin site uses permissions as follows: |
|---|
| 559 |
|
|---|
| 560 |
* Access to view the "add" form and add an object is limited to users with |
|---|
| 561 |
the "add" permission for that type of object. |
|---|
| 562 |
* Access to view the change list, view the "change" form and change an |
|---|
| 563 |
object is limited to users with the "change" permission for that type of |
|---|
| 564 |
object. |
|---|
| 565 |
* Access to delete an object is limited to users with the "delete" |
|---|
| 566 |
permission for that type of object. |
|---|
| 567 |
|
|---|
| 568 |
Permissions are set globally per type of object, not per specific object |
|---|
| 569 |
instance. For example, it's possible to say "Mary may change news stories," but |
|---|
| 570 |
it's not currently possible to say "Mary may change news stories, but only the |
|---|
| 571 |
ones she created herself" or "Mary may only change news stories that have a |
|---|
| 572 |
certain status, publication date or ID." The latter functionality is something |
|---|
| 573 |
Django developers are currently discussing. |
|---|
| 574 |
|
|---|
| 575 |
Default permissions |
|---|
| 576 |
------------------- |
|---|
| 577 |
|
|---|
| 578 |
Three basic permissions -- add, create and delete -- are automatically created |
|---|
| 579 |
for each Django model that has a ``class Admin`` set. Behind the scenes, these |
|---|
| 580 |
permissions are added to the ``auth_permission`` database table when you run |
|---|
| 581 |
``manage.py syncdb``. |
|---|
| 582 |
|
|---|
| 583 |
Note that if your model doesn't have ``class Admin`` set when you run |
|---|
| 584 |
``syncdb``, the permissions won't be created. If you initialize your database |
|---|
| 585 |
and add ``class Admin`` to models after the fact, you'll need to run |
|---|
| 586 |
``manage.py syncdb`` again. It will create any missing permissions for |
|---|
| 587 |
all of your installed apps. |
|---|
| 588 |
|
|---|
| 589 |
Custom permissions |
|---|
| 590 |
------------------ |
|---|
| 591 |
|
|---|
| 592 |
To create custom permissions for a given model object, use the ``permissions`` |
|---|
| 593 |
`model Meta attribute`_. |
|---|
| 594 |
|
|---|
| 595 |
This example model creates three custom permissions:: |
|---|
| 596 |
|
|---|
| 597 |
class USCitizen(models.Model): |
|---|
| 598 |
# ... |
|---|
| 599 |
class Meta: |
|---|
| 600 |
permissions = ( |
|---|
| 601 |
("can_drive", "Can drive"), |
|---|
| 602 |
("can_vote", "Can vote in elections"), |
|---|
| 603 |
("can_drink", "Can drink alcohol"), |
|---|
| 604 |
) |
|---|
| 605 |
|
|---|
| 606 |
The only thing this does is create those extra permissions when you run |
|---|
| 607 |
``syncdb``. |
|---|
| 608 |
|
|---|
| 609 |
.. _model Meta attribute: ../model_api/#meta-options |
|---|
| 610 |
|
|---|
| 611 |
API reference |
|---|
| 612 |
------------- |
|---|
| 613 |
|
|---|
| 614 |
Just like users, permissions are implemented in a Django model that lives in |
|---|
| 615 |
`django/contrib/auth/models.py`_. |
|---|
| 616 |
|
|---|
| 617 |
.. _django/contrib/auth/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py |
|---|
| 618 |
|
|---|
| 619 |
Fields |
|---|
| 620 |
~~~~~~ |
|---|
| 621 |
|
|---|
| 622 |
``Permission`` objects have the following fields: |
|---|
| 623 |
|
|---|
| 624 |
* ``name`` -- Required. 50 characters or fewer. Example: ``'Can vote'``. |
|---|
| 625 |
* ``content_type`` -- Required. A reference to the ``django_content_type`` |
|---|
| 626 |
database table, which contains a record for each installed Django model. |
|---|
| 627 |
* ``codename`` -- Required. 100 characters or fewer. Example: ``'can_vote'``. |
|---|
| 628 |
|
|---|
| 629 |
Methods |
|---|
| 630 |
~~~~~~~ |
|---|
| 631 |
|
|---|
| 632 |
``Permission`` objects have the standard data-access methods like any other |
|---|
| 633 |
`Django model`_. |
|---|
| 634 |
|
|---|
| 635 |
Authentication data in templates |
|---|
| 636 |
================================ |
|---|
| 637 |
|
|---|
| 638 |
The currently logged-in user and his/her permissions are made available in the |
|---|
| 639 |
`template context`_ when you use ``RequestContext``. |
|---|
| 640 |
|
|---|
| 641 |
.. admonition:: Technicality |
|---|
| 642 |
|
|---|
| 643 |
Technically, these variables are only made available in the template context |
|---|
| 644 |
if you use ``RequestContext`` *and* your ``TEMPLATE_CONTEXT_PROCESSORS`` |
|---|
| 645 |
setting contains ``"django.core.context_processors.auth"``, which is default. |
|---|
| 646 |
For more, see the `RequestContext docs`_. |
|---|
| 647 |
|
|---|
| 648 |
.. _RequestContext docs: ../templates_python/#subclassing-context-requestcontext |
|---|
| 649 |
|
|---|
| 650 |
Users |
|---|
| 651 |
----- |
|---|
| 652 |
|
|---|
| 653 |
The currently logged-in user, either a ``User`` instance or an``AnonymousUser`` |
|---|
| 654 |
instance, is stored in the template variable ``{{ user }}``:: |
|---|
| 655 |
|
|---|
| 656 |
{% if user.is_authenticated %} |
|---|
| 657 |
<p>Welcome, {{ user.username }}. Thanks for logging in.</p> |
|---|
| 658 |
{% else %} |
|---|
| 659 |
<p>Welcome, new user. Please log in.</p> |
|---|
| 660 |
{% endif %} |
|---|
| 661 |
|
|---|
| 662 |
Permissions |
|---|
| 663 |
----------- |
|---|
| 664 |
|
|---|
| 665 |
The currently logged-in user's permissions are stored in the template variable |
|---|
| 666 |
``{{ perms }}``. This is an instance of ``django.core.context_processors.PermWrapper``, |
|---|
| 667 |
which is a template-friendly proxy of permissions. |
|---|
| 668 |
|
|---|
| 669 |
In the ``{{ perms }}`` object, single-attribute lookup is a proxy to |
|---|
| 670 |
``User.has_module_perms``. This example would display ``True`` if the logged-in |
|---|
| 671 |
user had any permissions in the ``foo`` app:: |
|---|
| 672 |
|
|---|
| 673 |
{{ perms.foo }} |
|---|
| 674 |
|
|---|
| 675 |
Two-level-attribute lookup is a proxy to ``User.has_perm``. This example would |
|---|
| 676 |
display ``True`` if the logged-in user had the permission ``foo.can_vote``:: |
|---|
| 677 |
|
|---|
| 678 |
{{ perms.foo.can_vote }} |
|---|
| 679 |
|
|---|
| 680 |
Thus, you can check permissions in template ``{% if %}`` statements:: |
|---|
| 681 |
|
|---|
| 682 |
{% if perms.foo %} |
|---|
| 683 |
<p>You have permission to do something in the foo app.</p> |
|---|
| 684 |
{% if perms.foo.can_vote %} |
|---|
| 685 |
<p>You can vote!</p> |
|---|
| 686 |
{% endif %} |
|---|
| 687 |
{% if perms.foo.can_drive %} |
|---|
| 688 |
<p>You can drive!</p> |
|---|
| 689 |
{% endif %} |
|---|
| 690 |
{% else %} |
|---|
| 691 |
<p>You don't have permission to do anything in the foo app.</p> |
|---|
| 692 |
{% endif %} |
|---|
| 693 |
|
|---|
| 694 |
.. _template context: ../templates_python/ |
|---|
| 695 |
|
|---|
| 696 |
Groups |
|---|
| 697 |
====== |
|---|
| 698 |
|
|---|
| 699 |
Groups are a generic way of categorizing users so you can apply permissions, or |
|---|
| 700 |
some other label, to those users. A user can belong to any number of groups. |
|---|
| 701 |
|
|---|
| 702 |
A user in a group automatically has the permissions granted to that group. For |
|---|
| 703 |
example, if the group ``Site editors`` has the permission |
|---|
| 704 |
``can_edit_home_page``, any user in that group will have that permission. |
|---|
| 705 |
|
|---|
| 706 |
Beyond permissions, groups are a convenient way to categorize users to give |
|---|
| 707 |
them some label, or extended functionality. For example, you could create a |
|---|
| 708 |
group ``'Special users'``, and you could write code that could, say, give them |
|---|
| 709 |
access to a members-only portion of your site, or send them members-only e-mail |
|---|
| 710 |
messages. |
|---|
| 711 |
|
|---|
| 712 |
Messages |
|---|
| 713 |
======== |
|---|
| 714 |
|
|---|
| 715 |
The message system is a lightweight way to queue messages for given users. |
|---|
| 716 |
|
|---|
| 717 |
A message is associated with a ``User``. There's no concept of expiration or |
|---|
| 718 |
timestamps. |
|---|
| 719 |
|
|---|
| 720 |
Messages are used by the Django admin after successful actions. For example, |
|---|
| 721 |
``"The poll Foo was created successfully."`` is a message. |
|---|
| 722 |
|
|---|
| 723 |
The API is simple: |
|---|
| 724 |
|
|---|
| 725 |
* To create a new message, use |
|---|
| 726 |
``user_obj.message_set.create(message='message_text')``. |
|---|
| 727 |
* To retrieve/delete messages, use ``user_obj.get_and_delete_messages()``, |
|---|
| 728 |
which returns a list of ``Message`` objects in the user's queue (if any) |
|---|
| 729 |
and deletes the messages from the queue. |
|---|
| 730 |
|
|---|
| 731 |
In this example view, the system saves a message for the user after creating |
|---|
| 732 |
a playlist:: |
|---|
| 733 |
|
|---|
| 734 |
def create_playlist(request, songs): |
|---|
| 735 |
# Create the playlist with the given songs. |
|---|
| 736 |
# ... |
|---|
| 737 |
request.user.message_set.create(message="Your playlist was added successfully.") |
|---|
| 738 |
return render_to_response("playlists/create.html", |
|---|
| 739 |
context_instance=RequestContext(request)) |
|---|
| 740 |
|
|---|
| 741 |
When you use ``RequestContext``, the currently logged-in user and his/her |
|---|
| 742 |
messages are made available in the `template context`_ as the template variable |
|---|
| 743 |
``{{ messages }}``. Here's an example of template code that displays messages:: |
|---|
| 744 |
|
|---|
| 745 |
{% if messages %} |
|---|
| 746 |
<ul> |
|---|
| 747 |
{% for message in messages %} |
|---|
| 748 |
<li>{{ message }}</li> |
|---|
| 749 |
{% endfor %} |
|---|
| 750 |
</ul> |
|---|
| 751 |
{% endif %} |
|---|
| 752 |
|
|---|
| 753 |
Note that ``RequestContext`` calls ``get_and_delete_messages`` behind the |
|---|
| 754 |
scenes, so any messages will be deleted even if you don't display them. |
|---|
| 755 |
|
|---|
| 756 |
Finally, note that this messages framework only works with users in the user |
|---|
| 757 |
database. To send messages to anonymous users, use the `session framework`_. |
|---|
| 758 |
|
|---|
| 759 |
.. _session framework: ../sessions/ |
|---|
| 760 |
|
|---|
| 761 |
Other authentication sources |
|---|
| 762 |
============================ |
|---|
| 763 |
|
|---|
| 764 |
The authentication that comes with Django is good enough for most common cases, |
|---|
| 765 |
but you may have the need to hook into another authentication source -- that |
|---|
| 766 |
is, another source of usernames and passwords or authentication methods. |
|---|
| 767 |
|
|---|
| 768 |
For example, your company may already have an LDAP setup that stores a username |
|---|
| 769 |
and password for every employee. It'd be a hassle for both the network |
|---|
| 770 |
administrator and the users themselves if users had separate accounts in LDAP |
|---|
| 771 |
and the Django-based applications. |
|---|
| 772 |
|
|---|
| 773 |
So, to handle situations like this, the Django authentication system lets you |
|---|
| 774 |
plug in another authentication sources. You can override Django's default |
|---|
| 775 |
database-based scheme, or you can use the default system in tandem with other |
|---|
| 776 |
systems. |
|---|
| 777 |
|
|---|
| 778 |
Specifying authentication backends |
|---|
| 779 |
---------------------------------- |
|---|
| 780 |
|
|---|
| 781 |
Behind the scenes, Django maintains a list of "authentication backends" that it |
|---|
| 782 |
checks for authentication. When somebody calls |
|---|
| 783 |
``django.contrib.auth.authenticate()`` -- as described in "How to log a user in" |
|---|
| 784 |
above -- Django tries authenticating across all of its authentication backends. |
|---|
| 785 |
If the first authentication method fails, Django tries the second one, and so |
|---|
| 786 |
on, until all backends have been attempted. |
|---|
| 787 |
|
|---|
| 788 |
The list of authentication backends to use is specified in the |
|---|
| 789 |
``AUTHENTICATION_BACKENDS`` setting. This should be a tuple of Python path |
|---|
| 790 |
names that point to Python classes that know how to authenticate. These classes |
|---|
| 791 |
can be anywhere on your Python path. |
|---|
| 792 |
|
|---|
| 793 |
By default, ``AUTHENTICATION_BACKENDS`` is set to:: |
|---|
| 794 |
|
|---|
| 795 |
('django.contrib.auth.backends.ModelBackend',) |
|---|
| 796 |
|
|---|
| 797 |
That's the basic authentication scheme that checks the Django users database. |
|---|
| 798 |
|
|---|
| 799 |
The order of ``AUTHENTICATION_BACKENDS`` matters, so if the same username and |
|---|
| 800 |
password is valid in multiple backends, Django will stop processing at the |
|---|
| 801 |
first positive match. |
|---|
| 802 |
|
|---|
| 803 |
Writing an authentication backend |
|---|
| 804 |
--------------------------------- |
|---|
| 805 |
|
|---|
| 806 |
An authentication backend is a class that implements two methods: |
|---|
| 807 |
``get_user(id)`` and ``authenticate(**credentials)``. |
|---|
| 808 |
|
|---|
| 809 |
The ``get_user`` method takes an ``id`` -- which could be a username, database |
|---|
| 810 |
ID or whatever -- and returns a ``User`` object. |
|---|
| 811 |
|
|---|
| 812 |
The ``authenticate`` method takes credentials as keyword arguments. Most of |
|---|
| 813 |
the time, it'll just look like this:: |
|---|
| 814 |
|
|---|
| 815 |
class MyBackend: |
|---|
| 816 |
def authenticate(username=None, password=None): |
|---|
| 817 |
# Check the username/password and return a User. |
|---|
| 818 |
|
|---|
| 819 |
But it could also authenticate a token, like so:: |
|---|
| 820 |
|
|---|
| 821 |
class MyBackend: |
|---|
| 822 |
def authenticate(token=None): |
|---|
| 823 |
# Check the token and return a User. |
|---|
| 824 |
|
|---|
| 825 |
Either way, ``authenticate`` should check the credentials it gets, and it |
|---|
| 826 |
should return a ``User`` object that matches those credentials, if the |
|---|
| 827 |
credentials are valid. If they're not valid, it should return ``None``. |
|---|
| 828 |
|
|---|
| 829 |
The Django admin system is tightly coupled to the Django ``User`` object |
|---|
| 830 |
described at the beginning of this document. For now, the best way to deal with |
|---|
| 831 |
this is to create a Django ``User`` object for each user that exists for your |
|---|
| 832 |
backend (e.g., in your LDAP directory, your external SQL database, etc.) You |
|---|
| 833 |
can either write a script to do this in advance, or your ``authenticate`` |
|---|
| 834 |
method can do it the first time a user logs in. |
|---|
| 835 |
|
|---|
| 836 |
Here's an example backend that authenticates against a username and password |
|---|
| 837 |
variable defined in your ``settings.py`` file and creates a Django ``User`` |
|---|
| 838 |
object the first time a user authenticates:: |
|---|
| 839 |
|
|---|
| 840 |
from django.conf import settings |
|---|
| 841 |
from django.contrib.auth.models import User, check_password |
|---|
| 842 |
|
|---|
| 843 |
class SettingsBackend: |
|---|
| 844 |
""" |
|---|
| 845 |
Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD. |
|---|
| 846 |
|
|---|
| 847 |
Use the login name, and a hash of the password. For example: |
|---|
| 848 |
|
|---|
| 849 |
ADMIN_LOGIN = 'admin' |
|---|
| 850 |
ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de' |
|---|
| 851 |
""" |
|---|
| 852 |
def authenticate(self, username=None, password=None): |
|---|
| 853 |
login_valid = (settings.ADMIN_LOGIN == username) |
|---|
| 854 |
pwd_valid = check_password(password, settings.ADMIN_PASSWORD) |
|---|
| 855 |
if login_valid and pwd_valid: |
|---|
| 856 |
try: |
|---|
| 857 |
user = User.objects.get(username=username) |
|---|
| 858 |
except User.DoesNotExist: |
|---|
| 859 |
# Create a new user. Note that we can set password |
|---|
| 860 |
# to anything, because it won't be checked; the password |
|---|
| 861 |
# from settings.py will. |
|---|
| 862 |
user = User(username=username, password='get from settings.py') |
|---|
| 863 |
user.is_staff = True |
|---|
| 864 |
user.is_superuser = True |
|---|
| 865 |
user.save() |
|---|
| 866 |
return user |
|---|
| 867 |
return None |
|---|
| 868 |
|
|---|
| 869 |
def get_user(self, user_id): |
|---|
| 870 |
try: |
|---|
| 871 |
return User.objects.get(pk=user_id) |
|---|
| 872 |
except User.DoesNotExist: |
|---|
| 873 |
return None |
|---|