On 8/30/05, Jason F. McBrayer <
[EMAIL PROTECTED]> wrote:
On Tue, 2005-08-30 at 04:24 -0700, [EMAIL PROTECTED] wrote:
> Hi All
>
> Just starting with django and have very quickly got to the point where
> I can set out a simple little app.
>
> The next thing I need to be able to do is implement user
> authentication. Nothing too fancy just a basic one log in and you can
> do everything type set up.
>
> My question is what is the best way to go about this? Where should my
> security checks go, in the view? in the model?
A little bit of both. I'm doing a multi-user feed reader right now
(will be publicly released when I'm happy with it), so I've managed to
get this working. Basically you want a user model that can handle its
own authentication (it can be entirely database-backed, or it can be a
cache of some other source, such as ldap).
Then you need a login view, which will check authentication and if
successful, store the user_id in the session, and you need something
(probably a decorator) to check that the user is logged in where
required. Here's the login-relevant stuff from my app; some of which is
copied more-or-less-directly from django's admin framework:
models/engulf.py:
class User(meta.Model):
username = meta.CharField('Username', maxlength=64, unique=True)
password = meta.CharField('Password', maxlength=64)
feed = meta.ManyToManyField(Feed, filter_interface= meta.VERTICAL,
null=True, blank=True)
class META:
admin = meta.Admin()
def __repr__(self):
return self.username
def check_password(self,password):
if password == self.password:
return True
else:
return False
views/engulf.py:
class LoginManipulator(formfields.Manipulator):
def __init__(self):
self.fields = (
formfields.TextField(field_name="username",
length=30, maxlength=64,
is_required=True,
validator_list=[self.check_login]),
formfields.PasswordField(field_name="password",
length=30, maxlength=64,
is_required=True),
)
def check_login(self, field_data, all_data):
username = all_data['username']
password = all_data['password']
try:
u = users.get_object (username__exact=username)
if u.check_password(password):
return True
else:
raise validators.ValidationError("Invalid username/password.")
except users.UserDoesNotExist:
raise validators.ValidationError("Invalid username/password.")
def login(request):
manipulator = LoginManipulator()
if request.POST:
new_data = request.POST.copy()
errors = manipulator.get_validation_errors (new_data)
if not errors:
# successful login
u = users.get_object(username__exact=request.POST['username'])
request.session['user_id'] = u.id
if request.GET:
try:
next = self.request.GET['next']
return HttpResponseRedirect(next)
except KeyError:
pass
return HttpResponseRedirect('/engulf/')
else:
new_data = errors = {}
form = formfields.FormWrapper (manipulator, new_data, errors)
t = template_loader.get_template("engulf/login")
c = Context(request, { 'form': form,} )
return HttpResponse(t.render(c))
def logout(request):
try:
del request.session['user_id']
except KeyError:
pass
manipulator = LoginManipulator()
new_data = errors = {}
form = formfields.FormWrapper(manipulator, new_data, errors)
t = template_loader.get_template("engulf/login")
c = Context(request, {
'form': form,
'from_logout': "You have successfully logged out."
} )
return HttpResponse( t.render(c))
And views/util.py:
def redirect_to_login(next):
"Redirects the user to the login page, passing the given 'next' page"
response = HttpResponseRedirect('/engulf/accounts/login/?%s=%s' %
(REDIRECT_FIELD_NAME, next))
response['Pragma'] = "no cache"
response['Cache-Control'] = "no-cache"
return response
# decorators
def login_required(view_func):
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
def _checklogin(request, *args, **kwargs):
try:
user_id = request.session['user_id']
u = users.get_object(id__exact=user_id)
if user_id:
return view_func(request, *args, **kwargs)
else:
return redirect_to_login(request.path)
except (KeyError, users.UserDoesNotExist):
return redirect_to_login(request.path)
return _checklogin
A typical view function will be decorated with login_required like so
(as I'm using python 2.3):
def view(req):
blah blah blah...
view = util.login_required(blah)
> Anyone point me in the right direction? Or even a breif explanation of
> how django's admin authentcation works might get me going.
I arrived at this solution by looking at the anonymous session
documentation and the admin code. If my code samples don't help, you
might want to look there, too.
Good luck!
--
+----------------------------------------------------------------+
| Jason F. McBrayer [EMAIL PROTECTED] |
| "If you wish to make Pythocles wealthy, don't give him more |
| money; rather, reduce his desires." -- Epicurus |