Use Django’s Permalink Decorator with Generic Views
The permalink decorator is the way to keep your URLs DRY. The only place you need to define where something lives is in your urls.py. In your templates, just point to {{ object.get_absolute.url }}. The problem with how they tell you to do it in the book, the documentation, and elsewhere is that it doesn’t work right if you’re using the same view function more than once in all your urls.py files (which is bound to happen if you’re using a bunch of generic views). That’s because Django has no way of telling which one you mean.
Named URL patterns to the rescue.
If you have a URLpattern that looks like this:
(r'^(?P<slug>[-\w]+)/$’, list_detail.object_detail, log_detail),
Change it to this:
url(r'^(?P<slug>[-\w]+)/$’, list_detail.object_detail, log_detail, name=’log-detail’),
Note the addition of “url” to the start of the line and the “name=” bit at the end.
Now, in your model file(s), do the following:
Add this line to the top of the file:
from django.db.models import permalink
At the bottom of the model class do something similar to this:
@permalink
def get_absolute_url(self):
return ('log-detail', (), { 'slug': self.slug })
Any other question you have about this stuff is probably in the other sources.
Sources:
- Magus- on the #django IRC channel
- Django Book (print edition pages 324-325)
- Django documentation (permalink decorator)
- Django documentation (named URL patterns)
- cam macrae
Django Template System Basics
The long way
- Load a template
- Fill a
Context - Return a
HttpResponseobject
Like so:
from django.template import Template, Context
from django.http import HttpResponse
...
t = get_template('current_datetime.html')
html = t.render(Context({'current_date': now}))
return HttpResponse(html)
The short way: render_to_response
Like so:
from django.shortcuts import render_to_response
...
return render_to_response('current_datetime.html', {'current_date': now})
Source:
- The Django Book (pages 51, 52 of the print edition)
Things you probably want to install to get the most out of Django
Open and run:
sudo python setup.py install
Open and run:
sudo python setup.py install
Installing Django on OS X Leopard
If you haven’t already, stick your Leopard disk in and install Xcode 3.0.
Make a home for Django:
sudo mkdir /usr/local/django
cd /usr/local/django
Get the Django trunk from Subversion:
sudo svn co http://code.djangoproject.com/svn/django/trunk/
The Django trunk should now be in /usr/local/django/trunk/, and if you ever want to check out another branch, you have a nice spot to put it next to the trunk.
I’ve you’ve previously install Python yourself, pay attention here
Find out if you’re using the right version of Python:
which python
If you don’t see:
/usr/bin/python
then delete whatever version you have sitting in your path, such as one in /usr/local/:
sudo rm /usr/local/bin/python
Once “which python” gives you “/usr/bin/python“, make sure your Python site-packages is in the right place. Running this command:
python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
should give you:
/Library/Python/2.5/site-packages
End of previous Python caveat
Now make sure Python knows where to find Django:
ln -s /usr/local/django/trunk/django /Library/Python/2.5/site-packages/django
Put the django-admin.py script on your system path:
sudo ln -s /usr/local/django/trunk/django/bin/django-admin.py /usr/local/bin
Now you should have Django installed and ready to go. Run:
django-admin.py startproject project_name
and see.
If it works, cd into the folder it creates and try:
python manage.py runserver
Then go to localhost:8000 in your browser.
Django + MySQL:
If you want to use MySQL with Django, there’s a bit more to do. If you have MySQL ready to go, continue. Otherwise, go talk with Dan for a bit and come back here when you’re done.
Download the MySQLdb package. Stick in in /usr/local/src if you’re cool. Open it and edit site.cfg.
Change line ~ 13 from:
#mysql_config = /usr/local/bin/mysql_config
To:
mysql_config = /usr/local/mysql/bin/mysql_config
In _mysql.c:
Remove these lines (~ 37-39):
#ifndef uint
#define uint unsigned int
#endif
Go to the folder on the command line, then:
sudo python setup.py build
sudo python setup.py install
You might have to run the build command more than once. Don’t ask me why–I’m a copy and paster just like you.
That should do it. Try editing your settings.py file in your Django project and entering information for a MySQL database and see if it works.
If you experience something different than this or have any problems, please let me know directly or leave a comment.
Sources
Creating Basic Feeds in Django
This is actually pretty straight-forward if you’ve got things set up properly. I had a hard time at first, because I had the “sites” framework enabled but I wasn’t using it the right way. Basically, if you’ve got anything but the default example.com in the django_sites table, the syndication feed framework will be unhappy with you (presumably, unless you’re using the framework the right way).
Here’s what to do:
Put this in the urlpatterns in your base urls.py:
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}),
Put this in the top of your base urls.py (replace your_project_name and FeedName with your stuff):
from your_project_name.feeds import FeedName
feeds = {
'feedurl': FeedName,
}
Create a file called feeds.py and put it in the root of your project folder. This is what goes in it (your_project_name and FeedName are the same as the example above, replace ModelName and date_field with your stuff as well):
from django.contrib.syndication.feeds import Feed
from your_project_name.models import ModelName
class FeedName(Feed):
title = "Title of the website"
link = "/whatever/"
description = "What's the feed about, anyway?"
def items(self):
return ModelName.objects.order_by('-date_field')[:5]
You can change the [:5] to whatever number of items you want to show up in the feed, in case that wasn’t apparent.
The last step is to create templates for the feed just like you create for normal page views. Create a folder in your templates folder called feeds. The naming convention goes like this (feedurl is the same as you put in urls.py–like ‘blog’ or ‘latest’, etc.).
templates/feeds/feedurl_title.html
templates/feeds/feedurl_description.html
What goes in feedurl_title.html (at a minimum):
{{ obj.name }}
And feedurl_description.html:
{{ obj.description }}
Replace .title and .description with whatever the fields are called in your model. I usually use ‘name’ instead of ‘title’, for example.
I think it will work without having those templates, but you can customize what shows up in your feed pretty easily using that format. You can even rename what template files to use by putting this in your Feeds class (right below class FeedName(Feed):)
title_template = 'feeds/whatever.html'
description_template = 'feeds/whatever_else.html'
When you’re all done, you’ll be able to view your feeds at:
yoursite.tld/feeds/feedurl/
On a side note–the feed won’t show up in Safari while you’re viewing the feed on localhost for some reason. I’ve heard it works OK when it’s on a live server. Check it out in Firefox or something.
Sources:
Howto Upload Images in Django
I’ve chosen to keep my media in the /media/ folder of the same site (I know Django-people prefer to keep media on a separate server, but I don’t want to do that for a small-ish site, which is why I’d be likely to use Django).
In settings.py:
ADMIN_MEDIA_PREFIX = '/admin_media/'
This defaults to /media/, but I want that for my own media.
In urls.py:
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/Users/username/django/django_projects/project_name/media'}),
This is recommended against here. But that’s because they want you to serve all your static files from a separate server/domain as I mentioned before.
Set the other media configuration things:
MEDIA_ROOT = '/Users/username/django/django_projects/project_name/media/'
MEDIA_URL = '/media/'
In models.py:
logo = models.ImageField(upload_to="images/logos/", blank=True, help_text="Should be 50px wide")
This guy was having the same problem.
Optional Date Fields in Django
Adding blank=True on any field in your models.py file will keep the admin interface from requiring that field. That’s all you need to do if it’s a string field. If it’s an integer, boolean, or a date; you need to add null=True to the field as well.
date = models.DateField(blank=True, null=True)
Source
See also
When to use and when not to use NOT NULL in MySQL / Rails Migrations
Pluralization of Database Models in Django
Part of the “magic-removal” was apparently removing automatic pluralization. That’s a shame. That’s one thing I really dig about Rails.
In your models.py file:
class Meta:
verbose_name_plural = 'something'
So for a ‘Person’ model, you could put ‘people’. Now it will look right in the admin interface.
Image uploads in Django
Django uses the Python Image Library (PIL) to manage images.
(info)
What happened when I installed PIL from scratch.
I need Dan Benjamin to write Django tutorials so I don’t have to figure out the best way to do this myself! Not that I think this was the best way. That’s my point.
Getting Markdown to work with Django
In your view template put:
{% load markup %}
In your settings.py in the INSTALLED_APPS section, put:
'django.contrib.markup',
Install the Markdown library:
Install on OS X:
Download markdown.py and setup.py and run:
python setup.py install
This is what happened on my system:
running install
running build
running build_py
creating build
creating build/lib
copying markdown.py -> build/lib
running install_lib
copying build/lib/markdown.py -> /System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/site-packages
byte-compiling /System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/site-packages/markdown.py to markdown.pyc
I wonder if that was the wrong way to do that. It looks like it modified my system version of Python, which means if the system updates it, it will be overwritten, right?
Install on DreamHost
Basically, you just want to put the markdown.py file anywhere in your Python path. The simplest way is to just drop markdown.py in your django_projects directory. A slighty more complicated, but cleaner way (and actually the way I did it) is to create another directory for Python modules like this. I created a directory at the root of my Dreamhost account called “pylib”. You then need to add this directory to your python path by adjusting .bashrc and django.fcgi accordingly. If that makes sense, go for it. If not, just drop markdown.py in your django_projects — that’ll work fine.