From da5b0586d359390e2102703707afae65befe7f6d Mon Sep 17 00:00:00 2001 From: Jason Pellerin Date: Wed, 28 Jun 2006 17:07:26 +0000 Subject: Merge trunk to [3226] git-svn-id: http://code.djangoproject.com/svn/django/branches/multiple-db-support@3228 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- docs/authentication.txt | 109 +++++++++++++++++++++++++++++++++++++++++++----- docs/db-api.txt | 18 ++++++++ docs/serialization.txt | 85 +++++++++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+), 10 deletions(-) create mode 100644 docs/serialization.txt (limited to 'docs') diff --git a/docs/authentication.txt b/docs/authentication.txt index 79a4ed0875..3edbc21f7a 100644 --- a/docs/authentication.txt +++ b/docs/authentication.txt @@ -267,17 +267,25 @@ previous section). You can tell them apart with ``is_anonymous()``, like so:: How to log a user in -------------------- -To log a user in, do the following within a view:: +Depending on your task, you'll probably want to make sure to validate the +user's username and password before you log them in. The easiest way to do so +is to use the built-in ``authenticate`` and ``login`` functions from within a +view:: + + from django.contrib.auth import authenticate, login + username = request.POST['username'] + password = request.POST['password'] + user = authenticate(username=username, password=password) + if user is not None: + login(request, user) + +``authenticate`` checks the username and password. If they are valid it +returns a user object, otherwise it returns ``None``. ``login`` makes it so +your users don't have send a username and password for every request. Because +the ``login`` function uses sessions, you'll need to make sure you have +``SessionMiddleware`` enabled. See the `session documentation`_ for +more information. - from django.contrib.auth.models import SESSION_KEY - request.session[SESSION_KEY] = some_user.id - -Because this uses sessions, you'll need to make sure you have -``SessionMiddleware`` enabled. See the `session documentation`_ for more -information. - -This assumes ``some_user`` is your ``User`` instance. Depending on your task, -you'll probably want to make sure to validate the user's username and password. Limiting access to logged-in users ---------------------------------- @@ -672,3 +680,84 @@ Finally, note that this messages framework only works with users in the user database. To send messages to anonymous users, use the `session framework`_. .. _session framework: http://www.djangoproject.com/documentation/sessions/ + +Other Authentication Sources +============================ + +Django supports other authentication sources as well. You can even use +multiple sources at the same time. + +Using multiple backends +----------------------- + +The list of backends to use is controlled by the ``AUTHENTICATION_BACKENDS`` +setting. This should be a tuple of python path names. It defaults to +``('django.contrib.auth.backends.ModelBackend',)``. To add additional backends +just add them to your settings.py file. Ordering matters, so if the same +username and password is valid in multiple backends, the first one in the +list will return a user object, and the remaining ones won't even get a chance. + +Writing an authentication backend +--------------------------------- + +An authentication backend is a class that implements 2 methods: +``get_user(id)`` and ``authenticate(**credentials)``. The ``get_user`` method +takes an id, which could be a username, and database id, whatever, and returns +a user object. The ``authenticate`` method takes credentials as keyword +arguments. Many times it will just look like this:: + + class MyBackend: + def authenticate(username=None, password=None): + # check the username/password and return a user + +but it could also authenticate a token like so:: + + class MyBackend: + def authenticate(token=None): + # check the token and return a user + +Regardless, ``authenticate`` should check the credentials it gets, and if they +are valid, it should return a user object that matches those credentials. + +The Django admin system is tightly coupled to the Django User object described +at the beginning of this document. For now, the best way to deal with this is +to create a Django User object for each user that exists for your backend +(i.e. in your LDAP directory, your external SQL database, etc.) You can either +write a script to do this in advance, or your ``authenticate`` method can do +it the first time a user logs in. Here's an example backend that +authenticates against a username and password variable defined in your +``settings.py`` file and creates a Django user object the first time they +authenticate:: + + from django.conf import settings + from django.contrib.auth.models import User, check_password + + class SettingsBackend: + """ + Authenticate against vars in settings.py Use the login name, and a hash + of the password. For example: + + ADMIN_LOGIN = 'admin' + ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de' + """ + def authenticate(self, username=None, password=None): + login_valid = (settings.ADMIN_LOGIN == username) + pwd_valid = check_password(password, settings.ADMIN_PASSWORD) + if login_valid and pwd_valid: + try: + user = User.objects.get(username=username) + except User.DoesNotExist: + # Create a new user. Note that we can set password to anything + # as it won't be checked, the password from settings.py will. + user = User(username=username, password='get from settings.py') + user.is_staff = True + user.is_superuser = True + user.save() + return user + return None + + def get_user(self, user_id): + try: + return User.objects.get(pk=user_id) + except User.DoesNotExist: + return None diff --git a/docs/db-api.txt b/docs/db-api.txt index 5108949184..15b70ee028 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -60,6 +60,10 @@ the database until you explicitly call ``save()``. The ``save()`` method has no return value. +To create an object and save it all in one step see the `create`__ method. + +__ `create(**kwargs)`_ + Auto-incrementing primary keys ------------------------------ @@ -705,6 +709,20 @@ The ``DoesNotExist`` exception inherits from except ObjectDoesNotExist: print "Either the entry or blog doesn't exist." +``create(**kwargs)`` +~~~~~~~~~~~~~~~~~~~~ + +A convenience method for creating an object and saving it all in one step. Thus:: + + p = Person.objects.create(first_name="Bruce", last_name="Springsteen") + +and:: + + p = Person(first_name="Bruce", last_name="Springsteen") + p.save() + +are equivalent. + ``get_or_create(**kwargs)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/serialization.txt b/docs/serialization.txt new file mode 100644 index 0000000000..41954b7a0d --- /dev/null +++ b/docs/serialization.txt @@ -0,0 +1,85 @@ +========================== +Serializing Django objects +========================== + +.. note:: + + This API is currently under heavy development and may change -- + perhaps drastically -- in the future. + + You have been warned. + +Django's serialization framework provides a mechanism for "translating" Django +objects into other formats. Usually these other formats will be text-based and +used for sending Django objects over a wire, but it's possible for a +serializer to handle any format (text-based or not). + +Serializing data +---------------- + +At the highest level, serializing data is a very simple operation:: + + from django.core import serializers + data = serializers.serialize("xml", SomeModel.objects.all()) + +The arguments to the ``serialize`` function are the format to serialize the +data to (see `Serialization formats`_) and a QuerySet_ to serialize. +(Actually, the second argument can be any iterator that yields Django objects, +but it'll almost always be a QuerySet). + +.. _QuerySet: ../db_api/#retrieving-objects + +You can also use a serializer object directly:: + + xml_serializer = serializers.get_serializer("xml") + xml_serializer.serialize(queryset) + data = xml_serializer.getvalue() + +This is useful if you want to serialize data directly to a file-like object +(which includes a HTTPResponse_):: + + out = open("file.xml", "w") + xml_serializer.serialize(SomeModel.objects.all(), stream=out) + +.. _HTTPResponse: ../request_response/#httpresponse-objects + +Deserializing data +------------------ + +Deserializing data is also a fairly simple operation:: + + for obj in serializers.deserialize("xml", data): + do_something_with(obj) + +As you can see, the ``deserialize`` function takes the same format argument as +``serialize``, a string or stream of data, and returns an iterator. + +However, here it gets slightly complicated. The objects returned by the +``deserialize`` iterator *aren't* simple Django objects. Instead, they are +special ``DeserializedObject`` instances that wrap a created -- but unsaved -- +object and any associated relationship data. + +Calling ``DeserializedObject.save()`` saves the object to the database. + +This ensures that deserializing is a non-destructive operation even if the +data in your serialized representation doesn't match what's currently in the +database. Usually, working with these ``DeserializedObject`` instances looks +something like:: + + for deserialized_object in serializers.deserialize("xml", data): + if object_should_be_saved(deserialized_object): + obj.save() + +In other words, the usual use is to examine the deserialized objects to make +sure that they are "appropriate" for saving before doing so. Of course, if you trust your data source you could just save the object and move on. + +The Django object itself can be inspected as ``deserialized_object.object``. + +Serialization formats +--------------------- + +Django "ships" with a few included serializers, and there's a simple API for creating and registering your own... + +.. note:: + + ... which will be documented once the API is stable :) -- cgit v1.3