Changeset 3228
- Timestamp:
- 06/28/06 12:07:26 (2 years ago)
- Files:
-
- django/branches/multiple-db-support/django/conf/global_settings.py (modified) (1 diff)
- django/branches/multiple-db-support/django/contrib/admin/views/decorators.py (modified) (3 diffs)
- django/branches/multiple-db-support/django/contrib/auth/backends.py (copied) (copied from django/trunk/django/contrib/auth/backends.py)
- django/branches/multiple-db-support/django/contrib/auth/forms.py (modified) (3 diffs)
- django/branches/multiple-db-support/django/contrib/auth/__init__.py (modified) (1 diff)
- django/branches/multiple-db-support/django/contrib/auth/middleware.py (modified) (1 diff)
- django/branches/multiple-db-support/django/contrib/auth/models.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/contrib/auth/views.py (modified) (3 diffs)
- django/branches/multiple-db-support/django/contrib/comments/views/comments.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/contrib/markup/templatetags/markup.py (modified) (1 diff)
- django/branches/multiple-db-support/django/core/serializers (copied) (copied from django/trunk/django/core/serializers)
- django/branches/multiple-db-support/django/core/serializers/base.py (copied) (copied from django/trunk/django/core/serializers/base.py)
- django/branches/multiple-db-support/django/core/serializers/__init__.py (copied) (copied from django/trunk/django/core/serializers/__init__.py)
- django/branches/multiple-db-support/django/core/serializers/xml_serializer.py (copied) (copied from django/trunk/django/core/serializers/xml_serializer.py)
- django/branches/multiple-db-support/django/db/models/base.py (modified) (1 diff)
- django/branches/multiple-db-support/django/db/models/fields/__init__.py (modified) (1 diff)
- django/branches/multiple-db-support/django/db/models/loading.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/db/models/manager.py (modified) (1 diff)
- django/branches/multiple-db-support/django/db/models/query.py (modified) (1 diff)
- django/branches/multiple-db-support/docs/authentication.txt (modified) (2 diffs)
- django/branches/multiple-db-support/docs/db-api.txt (modified) (2 diffs)
- django/branches/multiple-db-support/docs/serialization.txt (copied) (copied from django/trunk/docs/serialization.txt)
- django/branches/multiple-db-support/tests/modeltests/basic/models.py (modified) (1 diff)
- django/branches/multiple-db-support/tests/modeltests/lookup/models.py (modified) (1 diff)
- django/branches/multiple-db-support/tests/modeltests/serializers (copied) (copied from django/trunk/tests/modeltests/serializers)
- django/branches/multiple-db-support/tests/modeltests/serializers/__init__.py (copied) (copied from django/trunk/tests/modeltests/serializers/__init__.py)
- django/branches/multiple-db-support/tests/modeltests/serializers/models.py (copied) (copied from django/trunk/tests/modeltests/serializers/models.py)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/multiple-db-support/django/conf/global_settings.py
r3055 r3228 282 282 # Django-powered features. 283 283 BANNED_IPS = () 284 285 ################## 286 # AUTHENTICATION # 287 ################## 288 289 AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) django/branches/multiple-db-support/django/contrib/admin/views/decorators.py
r2809 r3228 1 1 from django import http, template 2 2 from django.conf import settings 3 from django.contrib.auth.models import User, SESSION_KEY 3 from django.contrib.auth.models import User 4 from django.contrib.auth import authenticate, login 4 5 from django.shortcuts import render_to_response 5 6 from django.utils.translation import gettext_lazy … … 70 71 71 72 # Check the password. 72 username = request.POST.get('username', '')73 try:74 user = User.objects.get(username=username, is_staff=True)75 except User.DoesNotExist:73 username = request.POST.get('username', None) 74 password = request.POST.get('password', None) 75 user = authenticate(username=username, password=password) 76 if user is None: 76 77 message = ERROR_MESSAGE 77 78 if '@' in username: … … 87 88 # The user data is correct; log in the user in and continue. 88 89 else: 89 if user.check_password(request.POST.get('password', '')): 90 request.session[SESSION_KEY] = user.id 90 if user.is_staff: 91 login(request, user) 92 # TODO: set last_login with an event. 91 93 user.last_login = datetime.datetime.now() 92 94 user.save() django/branches/multiple-db-support/django/contrib/auth/forms.py
r3058 r3228 1 1 from django.contrib.auth.models import User 2 from django.contrib.auth import authenticate 2 3 from django.contrib.sites.models import Site 3 4 from django.template import Context, loader … … 21 22 forms.TextField(field_name="username", length=15, maxlength=30, is_required=True, 22 23 validator_list=[self.isValidUser, self.hasCookiesEnabled]), 23 forms.PasswordField(field_name="password", length=15, maxlength=30, is_required=True, 24 validator_list=[self.isValidPasswordForUser]), 24 forms.PasswordField(field_name="password", length=15, maxlength=30, is_required=True), 25 25 ] 26 26 self.user_cache = None … … 31 31 32 32 def isValidUser(self, field_data, all_data): 33 try: 34 self.user_cache = User.objects.get(username=field_data) 35 except User.DoesNotExist: 36 raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.") 37 38 def isValidPasswordForUser(self, field_data, all_data): 33 username = field_data 34 password = all_data.get('password', None) 35 self.user_cache = authenticate(username=username, password=password) 39 36 if self.user_cache is None: 40 return41 if not self.user_cache.check_password(field_data):42 self.user_cache = None43 37 raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.") 44 38 elif not self.user_cache.is_active: django/branches/multiple-db-support/django/contrib/auth/__init__.py
r2809 r3228 1 from django.core.exceptions import ImproperlyConfigured 2 3 SESSION_KEY = '_auth_user_id' 4 BACKEND_SESSION_KEY = '_auth_user_backend' 1 5 LOGIN_URL = '/accounts/login/' 2 6 REDIRECT_FIELD_NAME = 'next' 7 8 def load_backend(path): 9 i = path.rfind('.') 10 module, attr = path[:i], path[i+1:] 11 try: 12 mod = __import__(module, '', '', [attr]) 13 except ImportError, e: 14 raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e) 15 try: 16 cls = getattr(mod, attr) 17 except AttributeError: 18 raise ImproperlyConfigured, 'Module "%s" does not define a "%s" authentication backend' % (module, attr) 19 return cls() 20 21 def get_backends(): 22 from django.conf import settings 23 backends = [] 24 for backend_path in settings.AUTHENTICATION_BACKENDS: 25 backends.append(load_backend(backend_path)) 26 return backends 27 28 def authenticate(**credentials): 29 """ 30 If the given credentials, return a user object. 31 """ 32 for backend in get_backends(): 33 try: 34 user = backend.authenticate(**credentials) 35 except TypeError: 36 # this backend doesn't accept these credentials as arguments, try the next one. 37 continue 38 if user is None: 39 continue 40 # annotate the user object with the path of the backend 41 user.backend = str(backend.__class__) 42 return user 43 44 def login(request, user): 45 """ 46 Persist a user id and a backend in the request. This way a user doesn't 47 have to reauthenticate on every request. 48 """ 49 if user is None: 50 user = request.user 51 # TODO: It would be nice to support different login methods, like signed cookies. 52 request.session[SESSION_KEY] = user.id 53 request.session[BACKEND_SESSION_KEY] = user.backend 54 55 def logout(request): 56 """ 57 Remove the authenticated user's id from request. 58 """ 59 del request.session[SESSION_KEY] 60 del request.session[BACKEND_SESSION_KEY] 61 62 def get_user(request): 63 from django.contrib.auth.models import AnonymousUser 64 try: 65 user_id = request.session[SESSION_KEY] 66 backend_path = request.session[BACKEND_SESSION_KEY] 67 backend = load_backend(backend_path) 68 user = backend.get_user(user_id) or AnonymousUser() 69 except KeyError: 70 user = AnonymousUser() 71 return user django/branches/multiple-db-support/django/contrib/auth/middleware.py
r3113 r3228 5 5 def __get__(self, request, obj_type=None): 6 6 if self._user is None: 7 from django.contrib.auth.models import User, AnonymousUser, SESSION_KEY 8 try: 9 user_id = request.session[SESSION_KEY] 10 self._user = User.objects.get(pk=user_id) 11 except (KeyError, User.DoesNotExist): 12 self._user = AnonymousUser() 7 from django.contrib.auth import get_user 8 self._user = get_user(request) 13 9 return self._user 14 10 django/branches/multiple-db-support/django/contrib/auth/models.py
r3169 r3228 5 5 import datetime 6 6 7 SESSION_KEY = '_auth_user_id' 7 def check_password(raw_password, enc_password): 8 """ 9 Returns a boolean of whether the raw_password was correct. Handles 10 encryption formats behind the scenes. 11 """ 12 algo, salt, hsh = enc_password.split('$') 13 if algo == 'md5': 14 import md5 15 return hsh == md5.new(salt+raw_password).hexdigest() 16 elif algo == 'sha1': 17 import sha 18 return hsh == sha.new(salt+raw_password).hexdigest() 19 raise ValueError, "Got unknown password algorithm type in password." 8 20 9 21 class SiteProfileNotAvailable(Exception): … … 142 154 self.save() 143 155 return is_correct 144 algo, salt, hsh = self.password.split('$') 145 if algo == 'md5': 146 import md5 147 return hsh == md5.new(salt+raw_password).hexdigest() 148 elif algo == 'sha1': 149 import sha 150 return hsh == sha.new(salt+raw_password).hexdigest() 151 raise ValueError, "Got unknown password algorithm type in password." 156 return check_password(raw_password, self.password) 152 157 153 158 def get_group_permissions(self): django/branches/multiple-db-support/django/contrib/auth/views.py
r3114 r3228 4 4 from django.shortcuts import render_to_response 5 5 from django.template import RequestContext 6 from django.contrib.auth.models import SESSION_KEY7 6 from django.contrib.sites.models import Site 8 7 from django.http import HttpResponse, HttpResponseRedirect … … 20 19 if not redirect_to or '://' in redirect_to or ' ' in redirect_to: 21 20 redirect_to = '/accounts/profile/' 22 request.session[SESSION_KEY] = manipulator.get_user_id() 21 from django.contrib.auth import login 22 login(request, manipulator.get_user()) 23 23 request.session.delete_test_cookie() 24 24 return HttpResponseRedirect(redirect_to) … … 34 34 def logout(request, next_page=None, template_name='registration/logged_out.html'): 35 35 "Logs out the user and displays 'You are logged out' message." 36 from django.contrib.auth import logout 36 37 try: 37 del request.session[SESSION_KEY]38 logout(request) 38 39 except KeyError: 39 40 return render_to_response(template_name, {'title': _('Logged out')}, context_instance=RequestContext(request)) django/branches/multiple-db-support/django/contrib/comments/views/comments.py
r2981 r3228 6 6 from django.shortcuts import render_to_response 7 7 from django.template import RequestContext 8 from django.contrib.auth.models import SESSION_KEY9 8 from django.contrib.comments.models import Comment, FreeComment, PHOTOS_REQUIRED, PHOTOS_OPTIONAL, RATINGS_REQUIRED, RATINGS_OPTIONAL, IS_PUBLIC 10 9 from django.contrib.contenttypes.models import ContentType … … 220 219 # so they don't have to enter a username/password again. 221 220 if manipulator.get_user() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']): 222 request.session[SESSION_KEY] = manipulator.get_user_id() 221 from django.contrib.auth import login 222 login(request, manipulator.get_user()) 223 223 if errors or request.POST.has_key('preview'): 224 224 class CommentFormWrapper(forms.FormWrapper): django/branches/multiple-db-support/django/contrib/markup/templatetags/markup.py
r2809 r3228 28 28 return value 29 29 else: 30 return textile.textile(value )30 return textile.textile(value, encoding=settings.DEFAULT_CHARSET, output=settings.DEFAULT_CHARSET) 31 31 32 32 def markdown(value): django/branches/multiple-db-support/django/db/models/base.py
r3227 r3228 400 400 # Example: "UPDATE poll_choices SET _order = %s WHERE poll_id = %s AND id = %s" 401 401 sql = "UPDATE %s SET %s = %%s WHERE %s = %%s AND %s = %%s" % \ 402 (backend.quote_name(ordered_obj. db_table), backend.quote_name('_order'),403 backend.quote_name(ordered_obj. order_with_respect_to.column),404 backend.quote_name(ordered_obj. pk.column))405 rel_val = getattr(self, ordered_obj. order_with_respect_to.rel.field_name)402 (backend.quote_name(ordered_obj._meta.db_table), backend.quote_name('_order'), 403 backend.quote_name(ordered_obj._meta.order_with_respect_to.column), 404 backend.quote_name(ordered_obj._meta.pk.column)) 405 rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name) 406 406 cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)]) 407 407 transaction.commit_unless_managed() django/branches/multiple-db-support/django/db/models/fields/__init__.py
r3183 r3228 412 412 if lookup_type == 'range': 413 413 value = [str(v) for v in value] 414 elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'ne') :414 elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'ne') and hasattr(value, 'strftime'): 415 415 value = value.strftime('%Y-%m-%d') 416 416 else: django/branches/multiple-db-support/django/db/models/loading.py
r3227 r3228 33 33 return _app_list 34 34 35 def get_app(app_label ):36 "Returns the module containing the models for the given app_label. "35 def get_app(app_label, emptyOK = False): 36 "Returns the module containing the models for the given app_label. If the app has no models in it and 'emptyOK' is True, returns None." 37 37 get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish. 38 38 for app_name in settings.INSTALLED_APPS: 39 39 if app_label == app_name.split('.')[-1]: 40 return load_app(app_name) 40 mod = load_app(app_name) 41 if mod is None: 42 if emptyOK: 43 return None 44 else: 45 return mod 41 46 raise ImproperlyConfigured, "App with label %s could not be found" % app_label 42 47 … … 45 50 global _app_list 46 51 mod = __import__(app_name, '', '', ['models']) 52 if not hasattr(mod, 'models'): 53 return None 47 54 if mod.models not in _app_list: 48 55 _app_list.append(mod.models) django/branches/multiple-db-support/django/db/models/manager.py
r3131 r3228 70 70 return self.get_query_set().get(*args, **kwargs) 71 71 72 def get_or_create(self, *args, **kwargs): 73 return self.get_query_set().get_or_create(*args, **kwargs) 72 def get_or_create(self, **kwargs): 73 return self.get_query_set().get_or_create(**kwargs) 74 75 def create(self, **kwargs): 76 return self.get_query_set().create(**kwargs) 74 77 75 78 def filter(self, *args, **kwargs): django/branches/multiple-db-support/django/db/models/query.py
r3113 r3228 205 205 assert len(obj_list) == 1, "get() returned more than one %s -- it returned %s! Lookup parameters were %s" % (self.model._meta.object_name, len(obj_list), kwargs) 206 206 return obj_list[0] 207 208 def create(self, **kwargs): 209 """ 210 Create a new object with the given kwargs, saving it to the database 211 and returning the created object. 212 """ 213 obj = self.model(**kwargs) 214 obj.save() 215 return obj 207 216 208 217 def get_or_create(self, **kwargs): django/branches/multiple-db-support/docs/authentication.txt
r3087 r3228 268 268 -------------------- 269 269 270 To log a user in, do the following within a view:: 271 272 from django.contrib.auth.models import SESSION_KEY 273 request.session[SESSION_KEY] = some_user.id 274 275 Because this uses sessions, you'll need to make sure you have 276 ``SessionMiddleware`` enabled. See the `session documentation`_ for more 277 information. 278 279 This assumes ``some_user`` is your ``User`` instance. Depending on your task, 280 you'll probably want to make sure to validate the user's username and password. 270 Depending on your task, you'll probably want to make sure to validate the 271 user's username and password before you log them in. The easiest way to do so 272 is to use the built-in ``authenticate`` and ``login`` functions from within a 273 view:: 274 275 from django.contrib.auth import authenticate, login 276 username = request.POST['username'] 277 password = request.POST['password'] 278 user = authenticate(username=username, password=password) 279 if user is not None: 280 login(request, user) 281 282 ``authenticate`` checks the username and password. If they are valid it 283 returns a user object, otherwise it returns ``None``. ``login`` makes it so 284 your users don't have send a username and password for every request. Because 285 the ``login`` function uses sessions, you'll need to make sure you have 286 ``SessionMiddleware`` enabled. See the `session documentation`_ for 287 more information. 288 281 289 282 290 Limiting access to logged-in users … … 673 681 674 682 .. _session framework: http://www.djangoproject.com/documentation/sessions/ 683 684 Other Authentication Sources 685 ============================ 686 687 Django supports other authentication sources as well. You can even use 688 multiple sources at the same time. 689 690 Using multiple backends 691 ----------------------- 692 693 The list of backends to use is controlled by the ``AUTHENTICATION_BACKENDS`` 694 setting. This should be a tuple of python path names. It defaults to 695 ``('django.contrib.auth.backends.ModelBackend',)``. To add additional backends 696 just add them to your settings.py file. Ordering matters, so if the same 697 username and password is valid in multiple backends, the first one in the 698 list will return a user object, and the remaining ones won't even get a chance. 699 700 Writing an authentication backend 701 --------------------------------- 702 703 An authentication backend is a class that implements 2 methods: 704 ``get_user(id)`` and ``authenticate(**credentials)``. The ``get_user`` method 705 takes an id, which could be a username, and database id, whatever, and returns 706 a user object. The ``authenticate`` method takes credentials as keyword 707 arguments. Many times it will just look like this:: 708 709 class MyBackend: 710 def authenticate(username=None, password=None): 711 # check the username/password and return a user 712 713 but it could also authenticate a token like so:: 714 715 class MyBackend: 716 def authenticate(token=None): 717 # check the token and return a user 718 719 Regardless, ``authenticate`` should check the credentials it gets, and if they 720 are valid, it should return a user object that matches those credentials. 721 722 The Django admin system is tightly coupled to the Django User object described 723 at the beginning of this document. For now, the best way to deal with this is 724 to create a Django User object for each user that exists for your backend 725 (i.e. in your LDAP directory, your external SQL database, etc.) You can either 726 write a script to do this in advance, or your ``authenticate`` method can do 727 it the first time a user logs in. Here's an example backend that 728 authenticates against a username and password variable defined in your 729 ``settings.py`` file and creates a Django user object the first time they 730 authenticate:: 731 732 from django.conf import settings 733 from django.contrib.auth.models import User, check_password 734 735 class SettingsBackend: 736 """ 737 Authenticate against vars in settings.py Use the login name, and a hash 738 of the password. For example: 739 740 ADMIN_LOGIN = 'admin' 741 ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de' 742 """ 743 def authenticate(self, username=None, password=None): 744 login_valid = (settings.ADMIN_LOGIN == username) 745 pwd_valid = check_password(password, settings.ADMIN_PASSWORD) 746 if login_valid and pwd_valid: 747 try: 748 user = User.objects.get(username=username) 749 except User.DoesNotExist: 750 # Create a new user. Note that we can set password to anything 751 # as it won't be checked, the password from settings.py will. 752 user = User(username=username, password='get from settings.py') 753 user.is_staff = True 754 user.is_superuser = True 755 user.save() 756 return user 757 return None 758 759 def get_user(self, user_id): 760 try: 761 return User.objects.get(pk=user_id) 762 except User.DoesNotExist: 763 return None django/branches/multiple-db-support/docs/db-api.txt
r3141 r3228 60 60 61 61 The ``save()`` method has no return value. 62 63 To create an object and save it all in one step see the `create`__ method. 64 65 __ `create(**kwargs)`_ 62 66 63 67 Auto-incrementing primary keys … … 706 710 print "Either the entry or blog doesn't exist." 707 711 712 ``create(**kwargs)`` 713 ~~~~~~~~~~~~~~~~~~~~ 714 715 A convenience method for creating an object and saving it all in one step. Thus:: 716 717 p = Person.objects.create(first_name="Bruce", last_name="Springsteen") 718 719 and:: 720 721 p = Person(first_name="Bruce", last_name="Springsteen") 722 p.save() 723 724 are equivalent. 725 708 726 ``get_or_create(**kwargs)`` 709 727 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ django/branches/multiple-db-support/tests/modeltests/basic/models.py
r3075 r3228 348 348 >>> a101.headline 349 349 'Article 101' 350 """ 350 351 # You can create saved objects in a single step 352 >>> a10 = Article.objects.create(headline="Article 10", pub_date=datetime(2005, 7, 31, 12, 30, 45)) 353 >>> Article.objects.get(headline="Article 10") 354 <Article: Article 10> 355 """ django/branches/multiple-db-support/tests/modeltests/lookup/models.py
r3170 r3228 58 58 >>> Article.objects.filter(headline__startswith='Blah blah').count() 59 59 0L 60 61 # Date and date/time lookups can also be done with strings. 62 >>> Article.objects.filter(pub_date__exact='2005-07-27 00:00:00').count() 63 3L 60 64 61 65 # in_bulk() takes a list of IDs and returns a dictionary mapping IDs
