Use Django’s Permalink Decorator with Generic Views

Posted by Trey on March 10, 2008

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:

Django Template System Basics

Posted by Trey on March 05, 2008

The long way

  1. Load a template
  2. Fill a Context
  3. Return a HttpResponse object

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:

Things you probably want to install to get the most out of Django

Posted by Trey on February 26, 2008

Python Image Library (PIL)

Open and run:

sudo python setup.py install

Python Markdown library

Open and run:

sudo python setup.py install

See also.

Installing Django on OS X Leopard

Posted by Trey on February 26, 2008

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

Posted by Trey on September 23, 2007

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

Posted by Trey on February 27, 2007

Previously

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.

Technorati Tags:

Optional Date Fields in Django

Posted by Trey on December 27, 2006

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

Django model reference

See also

When to use and when not to use NOT NULL in MySQL / Rails Migrations

Pluralization of Database Models in Django

Posted by Trey on December 26, 2006

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

Posted by Trey on September 30, 2006

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

Posted by Trey on September 20, 2006

In your view template put:

{% load markup %}

In your settings.py in the INSTALLED_APPS section, put:

'django.contrib.markup',

Install the Markdown library:

Download

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

Croft tells it like it is:

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.