Tabla de Contenidos

Advanced Django

Authentication

Use of the user model

There is only one class in Django which is User, different types of users are instances of this class with other special attributes set.
Main attributes are: username, password, email, first_name, and last_name. However, there are others.
User classes and helper methods reference: https://docs.djangoproject.com/en/dev/ref/contrib/auth/

User creation

Using create_user function:

from django.contrib.auth.models import User
user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
# At this point, user is a User object that has already been saved to the database. 
user.last_name = 'Lennon'
user.save()

Change user password

To change user passwords we'll do:

from django.contrib.auth.models import User
u = User.objects.get(username='john')
u.set_password('new password')
u.save()

User authentication

User authenticate(), it takes credentials from keyword arguments and returns a User object if they were valid, if not returns None.

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    if user.is_active:
        print("User is valid, active and authenticated")
    else:
        print("The password is valid, but the account has been disabled!")
else:
    print("The username and password were incorrect.")

When a request is done, it is provided a request.user attribute. If the current user has not logged in the attribute will be set to an instance of AnonymousUser, otherwise it will be an instance of User. However you can tell it using is_authenticated() method:

if request.user.is_authenticated():
    # Do something for authenticated users.
else:
    # Do something for anonymous users.

Login and logout

To login a user: https://docs.djangoproject.com/en/dev/topics/auth/default/#django.contrib.auth.login.
To logout use the logout function:

from django.contrib.auth import logout
 
def logout_view(request):
    logout(request)
    # Redirect to a success page.

Authorization

Customizing authorization

Signals

Signals in Django

Django provides a way of intercept special notifications…

There are ohters like pre_init, class_prepared, pre_migrate, pre_syncdb, got_request_exception, connection_created

Connecting signals

The way to intercept a signal is using the connect() function or the receiver() decorator:

def my_callback(sender, **kwargs):
    print("Request finished!")
# .......
from django.core.signals import request_finished
request_finished.connect(my_callback)
# .......
from django.core.signals import request_finished
from django.dispatch import receiver
@receiver(request_finished)
def my_callback(sender, **kwargs):
    print("Request finished!")

The function Signal.connect has the next argument:

Signal.connect(receiver[, sender=None, weak=True, dispatch_uid=None])

Its arguments mean:

from myapp.models import MyModel
@receiver(pre_save, sender=MyModel)
def my_handler(sender, **kwargs):
... 
request_finished.connect(my_callback, dispatch_uid="my_unique_identifier")

Defining and sending signals

Signals are django.dispatch.Signal([providing_args=list]) instances. providing_args is a list of the names of arguments the signal will provide to listeners. To declare a pizza_done signal which provides receivers with toppics and size arguments:

import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

To send a signal, call either Signal.send() or Signal.send_robust(). Both return a list of tuple pairs [(receiver, response), … ]. They differ in how exceptions raised by receiver functions. send() does not catch any exceptions raised by receivers; it simply allows errors to propagate. Whereas send_robust() catches all errors derived from Python’s Exception class, and ensures all receivers are notified of the signal.

class PizzaStore(object):
    ...
    def send_pizza(self, toppings, size):
        pizza_done.send(sender=self.__class__, toppings=toppings, size=size)

To disconnect a receiver from a signal, call Signal.disconnect().