Prosthetic Conscience
Jason McBrayer's weblog; occasional personal notes and commentary
Mon, 05 Dec 2005
Simpler Apache FCGI Django
Inspired by some tips I saw someplace else, and some fiddling on my own, a simpler Django setup on Apache/mod_fcgi:
Snippet from httpd.conf:
<VirtualHost *:80>
ServerName mysite.dom
DocumentRoot /home/httpd/html/mysite/
AddHandler fastcgi-script fcg fcgi fpl fpy
RewriteEngine on
RewriteRule ^/media/.*$ - [L]
RewriteRule ^(/.*)$ /mysite.fcgi$1 [L]
SetEnv PYTHONPATH /home/httpd/html/mysite
SuexecUserGroup myuser mygroup
</VirtualHost>
And what mysite.fcgi looks like:
#!/usr/bin/python from flup.server.fcgi_fork import WSGIServer import os from django.core.handlers.wsgi import WSGIHandler os.environ[‘DJANGO_SETTINGS_MODULE’] = ‘mysite.settings’ handler = WSGIHandler() WSGIServer(handler).run()
You’ll have, of course, to change paths and userids to whatever you need. Features of this setup:
All requests are sent to Django, execpt for paths starting with /media/. This way you do not have to have RewriteRule lines for every application. This method assumes that your entire site except for media/images/etc. is served up with Django (using the flatpages application for everything that’s not an app view, for example).
mysite.fcgi is run as a dynamic FastCGI app. This means it will be started and stopped as necessary by mod_fastcgi process manager, and does not need to be individually added to the Apache config file (indeed, most of the above setup could be done from a .htaccess file assuming the VirtualHost was already set up and configured to accept .htaccess).
If the Apache server is set up with FastCGIWrapper, and Apache is set up correctly for suexec to work with virtual hosts, Django will run as myuser.mygroup, rather than as the Apache user. This is a great comfort in shared hosting environments.
Point 3 could also be accomplished by configuring your django runner script as a FastCGIExternalServer (in httpd.conf) and starting it manually as myuser.mygroup. This is a matter of personal preference. I prefer my way because httpd handles keeping one or more copies of my application running as needed; I don’t have to take further measures to make sure it gets restarted if it dies for some reason (crash, OOM kill, etc). I also like how it makes everything easier to configure (especially in a shared hosting environment, if everything is set up correctly beforehand). However, if you are allergic to Apache’s suexec, you may prefer the alternate method.
[ Posted: 14:15] | [ Category: /computing/django] | Permalink | Comments: 2 ]
Django alternate auth HOWTO
One of the most frequently-asked questions about Django is “How do I change the authentication system to (hook into my existing authentication system / use something other than the django database). In my first couple of posts in this section, I gave one answer. The method I gave works, and it has the advantage of working on a per-app basis (if that is what you need). However, it was also written before the Django authentication documentation was written. The method I posted uses anonymous sessions (from Django’s perspective) and does not really use the Django authentication framework. Most people will probably want to use as much of the Django authentication framework, however. As I’ve now figured it out (I’m sure I’m not the first, but I’ve never seen it comprehensively documented anywhere), I’m posting how to do this. Let me emphasize that I am not at all an expert on Django internals; I’m just posting my experiences and am open to correction on any points.
First, make an app to hold the new user model and (optionally) views for logging in and out.
In the model, you are going to be over-riding the standard django.models.auth.users model with one that subclasses it. So here is what you need.
from django.core import meta
from django.models import auth
# Create your models here.
class User(auth.User):
location = meta.CharField(maxlength=100, blank=True)
favourite_cheese = meta.CharField(maxlength=30, blank=True)
class META:
admin = meta.Admin(
fields = (
(None, {'fields': ('username', )}),
('Personal info', {'fields': ('first_name',
'last_name', 'email')}),
('Extra info', {'fields': ('location', “favourite_cheese”,)}),
('Permissions', {'fields': ('is_staff', 'is_active',
'is_superuser', 'user_permissions')}),
('Important dates', {'fields': ('last_login',
'date_joined')}),
('Groups', {'fields': ('groups',)}),
),
list_display = ('username', 'email', 'first_name',
'last_name', 'is_staff'),
list_filter = ('is_staff', 'is_superuser'),
search_fields = ('username', 'first_name', 'last_name',
'email'),
remove_fields = ('password_md5',)
)
replaces_module = 'auth.users'
def check_password(self, raw_password):
'''Override the auth framework's password checking '''
# Insert code for checking (e.g) ldap password here
if external_password_check(self.username, raw_password):
return True
else:
return False
def set_password(self, raw_password):
'''Override the auth framework's password setting '''
# Insert code for setting password.
external_password_set(self.username, raw_password)
return True
# end
This model does not have to be installed using “django-admin.py install fancyauth”, and indeed, doing so will fail. What you need to do, instead, is modify the auth_users table in your project’s database to add any fields you have added. In the above model, that is ‘location’ and ‘favourite_cheese’.
The convenience function create_user(username, email, password) is also broken by this change. Writing a replacement is left as an exercise to the reader (if needed; I don't find it all that useful). You will also need to set/change passwords either through a python interactive session, or through a custom view – it can't be changed in the admin system, though you can create users there.
This is basically the minimum you could do to use custom authentication with the Django authentication framework. Other things you might want to do:
Make the User model function as a cache of external user information (e.g., fill out fields from GECOS data in LDAP or Unix password file).
Login view automatically creates a user record if needed before checking password.
Make everything completely transparent with regard to Django authentication API and admin framework.
One final note: this authentication system is project-wide. If you have an app that has significantly different authentication needs from the rest of your site, you will need either to give it its own authentication framework, or (more likely) write your views in such a way that just being authenticated doesn’t imply much about what a user is authorized to do.
[ Posted: 13:25] | [ Category: /computing/django] | Permalink | Comments: 3 ]
Mark Twain
I am said to be a revolutionist in my sympathies, by birth, by breeding and by principle. I am always on the side of the revolutionists, because there never was a revolution unless there were some oppressive and intolerable conditions against which to revolute.
— Mark Twain
I especially like the coinage of “revolute.”
And here’s another:
(I used to be) a red-hot imperialist. I wanted the American eagle to go screaming into the Pacific …Why not spread its wings over the Philippines, I asked myself? … I said to myself, Here are a people who have suffered for three centuries. We can make them as free as ourselves, give them a government and country of their own, put a miniature of the American Constitution afloat in the Pacific, start a brand new republic to take its place among the free nations of the world. It seemed to me a great task to which we had addressed ourselves.
But I have thought some more, since then, and I have read carefully the treaty of Paris [which ended the Spanish-American War], and I have seen that we do not intend to free, but to subjugate the people of the Philippines. We have gone there to conquer, not to redeem.
It should, it seems to me, be our pleasure and duty to make those people free, and let them deal with their own domestic questions in their own way. And so I am an anti-imperialist. I am opposed to having the eagle put its talons on any other land.
— Mark Twain (1900, two years after the Spanish-American war began)
Le plus ça change, le plus le meme chose.
[ Posted: 08:35] | [ Category: /quotes] | Permalink | Comments: 0 ]
Powered by PyBlosxom
Subscribe