Skip to content

Everything A Django Developer Needs To Create Logins

by Paul Kenjora on February 8th, 2008

Disclaimer: This is Django 0.95 based and for now 0.96 compatible. There are better ways to do this, This is mainly a tutorial to help novice Django developers understand authentication. I strongly suggest you read this for understanding and then look at the comments for a wealth of better solutions…

We all at one point or another need to create a site that requires logins, which require signup, which require password recovery. I ran into this problem first when creating PeerGrab, it was a Digg clone. I’ve seen alot of posts asking how this is done and a few with snippets here and there. I’ve deceided to post all files relating to login, signup, and password recovery here. These solutions are meant to be simple, easy to use, and serve as examples for Django newbies. I think you will be able to easily integrate these files on any project.

I’ve used the code (pretty much unmodified) on several projects myself:

Model

The core of my login system is the assumption that the built in Django User system should be extensible but compatible with the built in admin interface and User models. Meaning I may want to add an avatar or other personal info that does not fit into the default User model. As a result the main component I have used is a model object called Bio that is 1:1 with User. Feel free to modify Bio any way you like without interrupting built in authentication.

models.py

Signup

Signup is meant to collect the minimum set of data required to create an account. This is desired in most cases as users can fill in extra information in the profile (not covered here as it is application specific). The signup I use takes: username, email, password (duplicate), and a captcha test. This is enough to create a bare minimum user, check against duplicate user names, validate password match, and prevent automatic account creation with an image challenge. For the curious I used PyCaptcha. An example signup page can be viewed at PeerGrab.com.

signup.py

signup.html

captcha.py

Login

The login form is pretty basic, it just checks username and password. This version does have the perk of allowing admins to lock the account using the Django admin interface. I awlays wanted to extend it to handle redirecting back to where the user chose to login from but I leave that up to the reader. Again this is 100% compatible with Django admin. As a matter of fact if you log in with admin you can access the site as well. It works vice-versa too so be careful about setting up user permissions (by default users are not admins so you should be OK). An example login page can be viewed at SharkOrBear.com

login.py

login.html

lost.html

change.html

URLs

Tying the Django user creating and management system all together are are the URLs for all these steps. Careful on changing these as many of these pages are interlinked. These are the paths used by all the files.

urls.py

The Environment

To get all this running you must enable some Django middleware. Make sure you have the following in your settings.py under INSTALLED_APPS:

  • django.contrib.auth
  • django.contrib.contenttypes
  • django.contrib.sessions

Conclusion

The above code should be enough to get you started on adding users to any Django project. I’d like to hear back from anyone interested in porting this to the new Django version (still using old forms, but hey it works). Also, if anyone takes the time to add Open ID to this please let me know. As with any large tutorial I’m sure I missed a few things. I leave it up to the community and the comments to fill in the blanks. Hope this helps.

The Source All Zipped Up

Here is all the code in the article packaged up in a nice zip:

Django Code For Creating Logins Using Old Forms

From → Forms, Tutorial

  • Brett
    The download URL is 404ing
  • Paul, just wanted to let you know I searched high and low trying to make head or tails out of how to do this. Thanks so much for making this available! I have about 12 hours total Django/Python experience and it took me about 2 hours to convert to newforms. I'm a Java Swing developer by day, and I'm really beginning to love this stuff. Thanks again!
  • Actually the easiest way to add a login form and membership to a website is to use Sentry, from Sentrylogin.com.
  • Hoadley
    I think if you just look at this:

    http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/views.py

    It'll answer your questions. Hook a url up to these views and viola. As for where it is in the docs, It's on the website somewhere or else I wouldn't have remembered it. Here, I found it in about 10 seconds:

    http://www.djangoproject.com/documentation/authentication/
    and
    http://www.djangobook.com
    The chapter about authentication and Users and Sessions

    The point trying to be made is that you are presenting code that is unnecessary and not using best practices in doing forms. Django has come a long way in 1.5 years.

    A novice is better served reading the django documentation and learning to work with a wealth of stuff that's already written. Your solutions all are oldforms based and while they may work, they aren't the best way for a novice to leverage django. What you don't realize is THIS is the HARD way.

    In python, you'd generally group related items together in one file unless each class/function is massive. Obviously, you are grouping things. But, If you've been following django in general you wouldn't group things like you are doing. Your run() just shows you've been doing it "your way" when most everyone else who programs in django wouldn't have a run function. They'd have a views.py file with all the view functions there.

    That's why you've been getting some negative and questioning comments.

    Don't take things too hard. That's the beauty of software development and also the flexibility of python. You should just update this article describing the "best way" to do these tasks with the current code base as a couple min reading those three links I gave you will show you easier and faster way of doing what you are talking about. Or if you don't want to do that put a disclaimer that this is a django 0.95 based solution. Cheers and good luck.
  • No need to come to my house, just download the zip file from this page, decompress to your project, sync the DB, and click refresh on your browser.

    I'm looking for something easier and or faster, especially given the audience, Django novices.

    James, how about a post addressing this very issue...
  • The default views are all documented right there on that page you linked, including the arguments they accept, the template names they expect and the variables they provide to the context. I'm not sure how much easier to use you can get from the docs, unless they come to your house and write your app for you.

    The book covers implementation of a sign-up view, but doesn't go into anything else -- it's not an exhaustive reference, like the djangoproject.com docs are.

    The relevant views have been in Django since the very first public release.

    The fact that they use oldforms is annoying, but tons of stuff in Django still uses oldforms; that's why it's still described as being in transition.

    And arrangement *does* make a difference; one of the great things about Python providing easy namespaces is that it's simple to arrange things in a way that makes sense based on what they do. You don't have to do any work to get a useful namespace, and you aren't bound by "one public thing per file" restrictions as in some languages. So why not take advantage of it to the fullest? You'll notice that django.contrib.auth puts all its views into one file and names them descriptively -- there's no logical reason to spread them out over a bunch of files, so it doesn't.
  • I did some research to find the default login, register, and password information here is what I leaned. These are the official alternates to this post on the same topic:

    1. Yes, default views do exist, using and/or extending the default views is still alot of re-work as documented by Stone Mind Blog.
    2. The official Django Book does not mention them but suggest using an approach like the one documented in this article.
    3. Using the default mechanism provided by Django was created/documented after I wrote the above code, it requires 0.96, my post is one solution from 0.95 days.
    4. The Django official docs lack significant information on this topic.
    5. It seems that even the new stuff uses oldforms.

    The great thing about Django is that there are many ways to solve the same issue at many different layers. I found the above solution to work for me and shared it with the community. Readers are free to evaluate their needs and choose either method. I agree that the offcial generic views approach would work for most but I also think new Django developers will find the above code simpler and more constructive.

    As far as how the files are arranged for login or logout, other than personal preference I can safely say it makes no difference. This code is meant to be a tutorial, its proven to work, and its in the spirit of Django: shared, free, and makes life for developers easy.
  • Paul, django.contrib.auth already *has* login, logout, password recovery, etc., built in. There's no need to write code for these, just point some URLs at the already-provided views that ship in Django. Hence django-registration does that (look at the URLConf it supplies).

    It doesn't provide templates because there's no such thing as a set of truly portable default templates -- I tried that once upon a time and learned the hard way. And if you want a captcha in the form, take a look at the documentation -- the registration form is designed to be subclassed for additional functionality (and provides several example subclasses showing how to do that).

    And I don't see how, for example, a "login" and a "logout" view both deserve their own complete files -- they're providing two parts of a higher-level functionality, so why *aren't* they in the same file?
  • James, thanks for the new forms registration link. Its a great registration snippet but I could not find any login or password recovrey code on the page. Also I'm not sure the registration code provides ready to go templates or a captcha field. Your link is a great addition to this post.

    The code is broken up into functional groups: registration, login, and recovery. I guess style wise I'm a big fan of breaking things down functionaly. I see your point regarding generic names like run but I think they work well in context of each file being a functional unit. Yes it would be better practice to give semantic meaning to functions vs. using "run", noted for future. Thanks for the suggestions.
  • Well, django.contrib.auth already provides login, logout, password change and password recovery, along with the necessary forms. For signup there's always this (released publicly about a year ago, uses newforms, provides a full, extensible solution):

    http://code.google.com/p/django-registration/


    As for idiomatic: one glaring thing is the way the views are strewn out over several files, and often given non-descript names like "run". A more natural solution (for Django, as well as for Python in general) would be a single file with a descriptive name, containing several auth-related view functions (again, each with descriptive names) and, possibly, a separate file for the forms.
  • This was implemented about 1.5 years ago. Django was young then and I couldn't find any signup, login, password recovery code out of the box. If anyone has a more current alternative please add it here, as I mentioned in the article I'm looking for improvements.

    Also I had to look up Idiomatic ad I'm still not sure what you mean by that in terms of the above code?
  • I can't help wondering why you reimplemented so many things that were already in django.contrib.auth (and reimplemented them in a fairly non-idiomatic way); is this just really ancient legacy code?
  • LMZ
    thanks for this!
  • Nick
    I don't think that it's useful for me, because it based on oldforms, but anyway thanks!
  • Holger Frey
    As a totally Django newbie – facing this question – I really appreciate your small tutorial and code examples. But would you be so kind and add a download link to an .tar or .zip file containing your files?

    Kind regards
    Holger
  • Kyle
    Wow, that code is really outdated...brings back (not-so-fond) memories :)

    I would highly suggest checking out James Bennet's registration app. You simply add a few templates and you have an entire registration / user activation system:
    http://code.google.com/p/django-registration/

    Regarding OpenID, just use Simon's handy app:
    http://code.google.com/p/django-openid/

    Pugging the two together looks pretty straightforward.
blog comments powered by Disqus