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:

PHP Frameworks

Posted by Trey on September 22, 2007

My obsession with all things new leads me to follow every friggin’ new framework under the sun.

Here are the ones worth noting for PHP (listed alphabetically). I’ll try to keep this list as up-to-date as I can.

Wikipedia has their own list as well.

Source

Originally posted here.

Related <select> Dropdowns in Rails Views

Posted by Trey on July 04, 2007

This is a pretty common scenario (I would think). You have a nested model that you want to be able to select the item that the current item depends on (the client for a project, the manufacturer for an appliance). Using form_for, you can do something like this.

Chat with JTJ:

What you do is create a select tag with the “select” method like so: (using the client/project scenario)

f.select(:client_id,

The next value you pass to the select method has to be an array of text/value pairs

like this: [ [ "Jason Johnson", 1], ["Trey Piepmeier", 2], ["Royall", 3] ]

In order to create this array, you do a find on your clients table and use Ruby’s “collect” method.

like so:

Client.find(:all).collect {|c| [ c.name, c.id ]}

So, altogether now:

f.select(:client_id, Client.find(:all).collect {|c| [ c.name, c.id ] })

Other sources:

Title Case in ERb

Posted by Trey on July 04, 2007

Use .titleize or .titlecase. I’m using this in the <title> tag of my application.rhtml:

<%= controller.action_name.titleize %>

Source

Setting up a new Rails project in Subversion

Posted by Trey on June 25, 2007

Create a folder to put all the junk you need to set things up.

mkdir svn_setup
cd svn_setup

Create the standard SVN folder structure.

mkdir tags
mkdir branches

Create a new Rails project and rename it to be the trunk folder.

rails project_name
mv project_name trunk

The reason to do this is so your database.yml file (among others) will have the right project name instead of trunk_development, etc.

A little housekeeping before putting the files into the repository.

cd trunk
rm -r tmp/*
rm -r log/*
mv config/database.yml config/database_example.yml

Put the files into the repository.

cd ..
svn import . svn_project_url -m "initial import of blank Rails project" --username whathaveyou

Checkout the files and tell Subversion to ignore some files.

cd ..
svn co svn_project_url/trunk project_name
cd project_name
cp config/database_example.yml config/database.yml
svn propset svn:ignore database.yml config/
svn propset svn:ignore "*" log/
svn propset svn:ignore "*" tmp/

If you want, setup Rails with svn:externals to that it will be ready for you to lock it into a particular version for stability.

svn propedit svn:externals vendor/

In the file that pops up, enter this (or enter whatever version you want to use–such as http://dev.rubyonrails.org/svn/rails/trunk/ for edge):

rails http://dev.rubyonrails.org/svn/rails/tags/rel_1-2-3/

Save then close the file.

Check the changes back into the repository.

svn ci -m "Ignore database.yml, log/, and temp/.  Set up Rails with svn:extnrnals"

Then update your checkout to get the Rails external to load.

svn up

Other things:

When you’re done with everything you can delete the svn_setup folder. I think I’m going to keep mine around for a slight head start on more projects.

Don’t forget to use the -c option when you run script/generate to automatically add the files to Subversion.

script/generate scaffold_resource angryfarmer name:string bales_of_hay:integer -c

When installing plugins, use the -x option to make it an svn:external

script/plugin install -x robot_cow

Source

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: