Django

Code

Changeset 3228

Show
Ignore:
Timestamp:
06/28/06 12:07:26 (2 years ago)
Author:
jpellerin
Message:

Merge trunk to [3226]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/multiple-db-support/django/conf/global_settings.py

    r3055 r3228  
    282282# Django-powered features. 
    283283BANNED_IPS = () 
     284 
     285################## 
     286# AUTHENTICATION # 
     287################## 
     288 
     289AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) 
  • django/branches/multiple-db-support/django/contrib/admin/views/decorators.py

    r2809 r3228  
    11from django import http, template 
    22from django.conf import settings 
    3 from django.contrib.auth.models import User, SESSION_KEY 
     3from django.contrib.auth.models import User 
     4from django.contrib.auth import authenticate, login 
    45from django.shortcuts import render_to_response 
    56from django.utils.translation import gettext_lazy 
     
    7071 
    7172        # 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
    7677            message = ERROR_MESSAGE 
    7778            if '@' in username: 
     
    8788        # The user data is correct; log in the user in and continue. 
    8889        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. 
    9193                user.last_login = datetime.datetime.now() 
    9294                user.save() 
  • django/branches/multiple-db-support/django/contrib/auth/forms.py

    r3058 r3228  
    11from django.contrib.auth.models import User 
     2from django.contrib.auth import authenticate 
    23from django.contrib.sites.models import Site 
    34from django.template import Context, loader 
     
    2122            forms.TextField(field_name="username", length=15, maxlength=30, is_required=True, 
    2223                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), 
    2525        ] 
    2626        self.user_cache = None 
     
    3131 
    3232    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) 
    3936        if self.user_cache is None: 
    40             return 
    41         if not self.user_cache.check_password(field_data): 
    42             self.user_cache = None 
    4337            raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.") 
    4438        elif not self.user_cache.is_active: 
  • django/branches/multiple-db-support/django/contrib/auth/__init__.py

    r2809 r3228  
     1from django.core.exceptions import ImproperlyConfigured 
     2 
     3SESSION_KEY = '_auth_user_id' 
     4BACKEND_SESSION_KEY = '_auth_user_backend' 
    15LOGIN_URL = '/accounts/login/' 
    26REDIRECT_FIELD_NAME = 'next' 
     7 
     8def 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 
     21def 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 
     28def 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 
     44def 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 
     55def 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 
     62def 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  
    55    def __get__(self, request, obj_type=None): 
    66        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) 
    139        return self._user 
    1410 
  • django/branches/multiple-db-support/django/contrib/auth/models.py

    r3169 r3228  
    55import datetime 
    66 
    7 SESSION_KEY = '_auth_user_id' 
     7def 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." 
    820 
    921class SiteProfileNotAvailable(Exception): 
     
    142154                self.save() 
    143155            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) 
    152157 
    153158    def get_group_permissions(self): 
  • django/branches/multiple-db-support/django/contrib/auth/views.py

    r3114 r3228  
    44from django.shortcuts import render_to_response 
    55from django.template import RequestContext 
    6 from django.contrib.auth.models import SESSION_KEY 
    76from django.contrib.sites.models import Site 
    87from django.http import HttpResponse, HttpResponseRedirect 
     
    2019            if not redirect_to or '://' in redirect_to or ' ' in redirect_to: 
    2120                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()) 
    2323            request.session.delete_test_cookie() 
    2424            return HttpResponseRedirect(redirect_to) 
     
    3434def logout(request, next_page=None, template_name='registration/logged_out.html'): 
    3535    "Logs out the user and displays 'You are logged out' message." 
     36    from django.contrib.auth import logout 
    3637    try: 
    37         del request.session[SESSION_KEY] 
     38        logout(request) 
    3839    except KeyError: 
    3940        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  
    66from django.shortcuts import render_to_response 
    77from django.template import RequestContext 
    8 from django.contrib.auth.models import SESSION_KEY 
    98from django.contrib.comments.models import Comment, FreeComment, PHOTOS_REQUIRED, PHOTOS_OPTIONAL, RATINGS_REQUIRED, RATINGS_OPTIONAL, IS_PUBLIC 
    109from django.contrib.contenttypes.models import ContentType 
     
    220219    # so they don't have to enter a username/password again. 
    221220    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()) 
    223223    if errors or request.POST.has_key('preview'): 
    224224        class CommentFormWrapper(forms.FormWrapper): 
  • django/branches/multiple-db-support/django/contrib/markup/templatetags/markup.py

    r2809 r3228  
    2828        return value 
    2929    else: 
    30         return textile.textile(value
     30        return textile.textile(value, encoding=settings.DEFAULT_CHARSET, output=settings.DEFAULT_CHARSET
    3131 
    3232def markdown(value): 
  • django/branches/multiple-db-support/django/db/models/base.py

    r3227 r3228  
    400400    # Example: "UPDATE poll_choices SET _order = %s WHERE poll_id = %s AND id = %s" 
    401401    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) 
    406406    cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)]) 
    407407    transaction.commit_unless_managed() 
  • django/branches/multiple-db-support/django/db/models/fields/__init__.py

    r3183 r3228  
    412412        if lookup_type == 'range': 
    413413            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')
    415415            value = value.strftime('%Y-%m-%d') 
    416416        else: 
  • django/branches/multiple-db-support/django/db/models/loading.py

    r3227 r3228  
    3333    return _app_list 
    3434 
    35 def get_app(app_label): 
    36     "Returns the module containing the models for the given app_label.
     35def 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.
    3737    get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish. 
    3838    for app_name in settings.INSTALLED_APPS: 
    3939        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 
    4146    raise ImproperlyConfigured, "App with label %s could not be found" % app_label 
    4247 
     
    4550    global _app_list 
    4651    mod = __import__(app_name, '', '', ['models']) 
     52    if not hasattr(mod, 'models'): 
     53        return None 
    4754    if mod.models not in _app_list: 
    4855        _app_list.append(mod.models) 
  • django/branches/multiple-db-support/django/db/models/manager.py

    r3131 r3228  
    7070        return self.get_query_set().get(*args, **kwargs) 
    7171 
    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) 
    7477 
    7578    def filter(self, *args, **kwargs): 
  • django/branches/multiple-db-support/django/db/models/query.py

    r3113 r3228  
    205205        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) 
    206206        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 
    207216 
    208217    def get_or_create(self, **kwargs): 
  • django/branches/multiple-db-support/docs/authentication.txt

    r3087 r3228  
    268268-------------------- 
    269269 
    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. 
     270Depending on your task, you'll probably want to make sure to validate the  
     271user's username and password before you log them in. The easiest way to do so  
     272is to use the built-in ``authenticate`` and ``login`` functions from within a  
     273view:: 
     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  
     283returns a user object, otherwise it returns ``None``. ``login`` makes it so  
     284your users don't have send a username and password for every request. Because  
     285the ``login`` function uses sessions, you'll need to make sure you have  
     286``SessionMiddleware`` enabled. See the `session documentation`_ for  
     287more information. 
     288 
    281289 
    282290Limiting access to logged-in users 
     
    673681 
    674682.. _session framework: http://www.djangoproject.com/documentation/sessions/ 
     683 
     684Other Authentication Sources 
     685============================ 
     686 
     687Django supports other authentication sources as well. You can even use  
     688multiple sources at the same time. 
     689 
     690Using multiple backends 
     691----------------------- 
     692 
     693The list of backends to use is controlled by the ``AUTHENTICATION_BACKENDS``  
     694setting. This should be a tuple of python path names. It defaults to  
     695``('django.contrib.auth.backends.ModelBackend',)``. To add additional backends 
     696just add them to your settings.py file. Ordering matters, so if the same 
     697username and password is valid in multiple backends, the first one in the 
     698list will return a user object, and the remaining ones won't even get a chance. 
     699 
     700Writing an authentication backend 
     701--------------------------------- 
     702 
     703An authentication backend is a class that implements 2 methods:  
     704``get_user(id)`` and ``authenticate(**credentials)``. The ``get_user`` method  
     705takes an id, which could be a username, and database id, whatever, and returns  
     706a user object. The  ``authenticate`` method takes credentials as keyword  
     707arguments. 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 
     713but 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 
     719Regardless, ``authenticate`` should check the credentials it gets, and if they  
     720are valid, it should return a user object that matches those credentials. 
     721 
     722The Django admin system is tightly coupled to the Django User object described  
     723at the beginning of this document. For now, the best way to deal with this is  
     724to 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  
     726write a script to do this in advance, or your ``authenticate`` method can do  
     727it the first time a user logs in.  Here's an example backend that  
     728authenticates against a username and password variable defined in your  
     729``settings.py`` file and creates a Django user object the first time they  
     730authenticate:: 
     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  
    6060 
    6161The ``save()`` method has no return value. 
     62 
     63To create an object and save it all in one step see the `create`__ method. 
     64 
     65__ `create(**kwargs)`_ 
    6266 
    6367Auto-incrementing primary keys 
     
    706710        print "Either the entry or blog doesn't exist." 
    707711 
     712``create(**kwargs)`` 
     713~~~~~~~~~~~~~~~~~~~~ 
     714 
     715A 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     
     719and:: 
     720 
     721    p = Person(first_name="Bruce", last_name="Springsteen") 
     722    p.save() 
     723     
     724are equivalent. 
     725 
    708726``get_or_create(**kwargs)`` 
    709727~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  • django/branches/multiple-db-support/tests/modeltests/basic/models.py

    r3075 r3228  
    348348>>> a101.headline 
    349349'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  
    5858>>> Article.objects.filter(headline__startswith='Blah blah').count() 
    59590L 
     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() 
     633L 
    6064 
    6165# in_bulk() takes a list of IDs and returns a dictionary mapping IDs