Blog

Django @ PyConIt 2

Posted May 20, 2008, 4:50 p.m.

The second italian python conference was a great success: over 300 people, great location and very interesting talks.

Django presence was really better than the past year, I met a lot of people interested in it and I hope that this will help to get Django more considered into italian’s web applications marketplace.

Carlo Miron and Daniele Varrazzo started with an interactive track where code was written directly and discussed with partecipants.

In the afternoon I talked about Django new features and advanced uses, it was great but I had not enough time…my fault, too many slides and I was a bit nervous :) slides are available at PyConIt website and slideshare.

The day after Antonio Cavedoni talked about a django-based pangramming web application and its own Google App Engine version during a lighting talk session.

Add to: Add to deliciousAdd to DiggAdd to FurlAdd to redditAdd to YahooAdd to NewsvineAdd to Spurl

Tags: django pyconit2 python pyconit pycon


Babel and Django integration updates

Posted Aug. 20, 2007, 6:50 p.m.

The middleware that I’ve posted on djangosnippets and on this blog entry now is included into Babel’s contrib addons. Ramiro Morales has also written some very useful template filters for dates, decimals and currencies.

Have a look at BabelDjango for more details.

Add to: Add to deliciousAdd to DiggAdd to FurlAdd to redditAdd to YahooAdd to NewsvineAdd to Spurl

Tags: django babel i18n localization l10n


Django based photo gallery tutorial

Posted Aug. 8, 2007, 5:55 p.m.

This tutorial will show how you can build a working photo gallery for your django-powered website.

Requirements

I assume that you have a Python, PIL, Django 0.96 and django-tagging running and working properly.

First of it all create “gallery” and “utils” applications:

$ python manage.py startapp gallery
$ python manage.py startapp utils

You need to have the current user’s info outside requests, have a look at CookBookThreadlocalsAndUser and add the middleware in your “MIDDLEWARE_CLASSES” settings.

Now you must have custom upload fields and template filters. Download “fs.py” and “imaging.py” from CustomUploadAndFilters and place it into your “utils” application directory. Create the templatetags module directory and put inside it the “image_filters.py” file containing the code shown in the wiki page and adjust the “import” statements:

# Adjust your paths to ‘imaging’ and ‘fs’
from myproject.utils.imaging import fit, fit_crop
from myproject.utils.fs import add_to_basename

And add both applications into your “settings.py”:

INSTALLED_APPS = (
    … CUT …
    ‘myproject.utils’,
    ‘myproject.gallery’,
    … CUT …
)

Models

Let’s have a look at the gallery’s models:

from django.db import models
from django.db.models import permalink
from django.conf import settings
from django.contrib.auth.models import User

from myproject.middleware import threadlocals
from myproject.utils.fields import AutoImageField
from myproject.tagging.fields import TagField
from myproject.utils.templatetags.image_filters import thumb

class GalleryManager(models.Manager):
    def get_query_set(self):
        return super(GalleryManager, self).get_query_set().filter(published=True)

class Gallery(models.Model):
    title = models.CharField(maxlength=75)
    slug = models.SlugField(maxlength=75, prepopulate_from=(‘title’,), unique=True)
    description = models.TextField(blank=True)
    published = models.BooleanField()
    author = models.ForeignKey(User, blank=True,
                               help_text=’Keep blank, it will be set to current user’)

    admin_objects = models.Manager()
    objects = GalleryManager()

    def thumb(self):
        try:
            photo = Photo.objects.filter(gallery=self.id)[0]
        except IndexError:
            pass
        else:
            return photo.image

    def get_absolute_url(self):
        return (‘myproject.gallery.views.photo_list’, None, {‘slug’: self.slug})
    get_absolute_url = permalink(get_absolute_url)

    def __str__(self):
        return self.title

    def save(self):
        if not self.id:
            self.author = threadlocals.get_current_user()
        super(Gallery, self).save()

    class Meta:
        verbose_name_plural = ‘Gallery’

    class Admin:
        list_display = (‘__str__’, ‘author’, ‘published’,)

class PhotoManager(models.Manager):
    def get_query_set(self):
        return super(PhotoManager, self).get_query_set().filter(gallery__published=True)

class Photo(models.Model):
    gallery = models.ForeignKey(Gallery)
    image = AutoImageField(max_width=760, help_text=’Automatically resized’)
    title = models.CharField(maxlength=75)
    slug = models.SlugField(maxlength=75, prepopulate_from=(‘title’,), unique=True)
    description = models.TextField(blank=True)
    posted = models.DateTimeField()
    tags = TagField(blank=True)

    admin_objects = models.Manager()
    objects = PhotoManager()

    def __str__(self):
        return self.title

    def _image_repr(self):
        return ‘<img src=”%s” />’ % thumb(self.image, ‘width=220’)
    _image_repr.short_description = “Image”
    _image_repr.allow_tags = True

    class Admin:
        list_display = (‘_image_repr’, ‘__str__’, ‘gallery’, ‘posted’)
        list_per_page = 10

    class Meta:
        ordering = (‘-posted’,)
        get_latest_by = ‘posted’

“Gallery” and “Photo” models are related by a “ForeignKey” field, I didn’t use a many-to-many relationship because I prefer to use tags to categorize gallery photos between different galleries.

Gallery Model

I use a custom manager for the Gallery model that returns only published galleries:

class GalleryManager(models.Manager):
    def get_query_set(self):
        return super(GalleryManager, self).get_query_set().filter(published=True)

I also created a “thumb” method to get the first related photo image:

def thumb(self):
    try:
        photo = Photo.objects.filter(gallery=self.id)[0]
    except IndexError:
        pass
    else:
        return photo.image

The “get_absolute_url” method uses the permalink decorator, that allows to generate URLs for model instances reading the URL conf of your project. Change the first argument of the returned tuple according to your project name:

def get_absolute_url(self):
    return (‘myproject.gallery.views.photo_list’, None, {‘slug’: self.slug})
get_absolute_url = permalink(get_absolute_url)

Photo model

“Photo” model uses a custom manager too and it returns only published gallery’s photos:

class PhotoManager(models.Manager):
    def get_query_set(self):
        return super(PhotoManager, self).get_query_set().filter(gallery__published=True)

“Photo” image is an “AutoImageField” field, you may change the “max_width” or add the “max_height” keyword argument:

image = AutoImageField(max_width=760, help_text=’Automatically resized’)

Photos are uploaded into a “photo” directory inside your media directory, it must be writeable by the process that is running Django. You should change the upload directory setting the “upload_to” keyword argument.

Photos are categorized using the django-tagging generic application, you may change your import statement if you have installed it instead of having a checkout in your project directory.

The following code allows to have thumbnails in your admin list page using the “thumb” template filter:

    def _image_repr(self):
        return ‘<img src=”%s” />’ % thumb(self.image, ‘width=220’)
    _image_repr.short_description = “Image”
    _image_repr.allow_tags = True

    class Admin:
        list_display = (‘_image_repr’, ‘__str__’, ‘gallery’, ‘posted’)
        list_per_page = 10

Passing a string to the “thumb” method is dirt, but both “crop” and “thumb” are both template filters, it could be useful to rewrite some lines of code to have a much cleaner code.

Views

I am using a custom view to get photos related to the selected gallery:

from django.http import Http404
from django.views.generic.list_detail import object_list

from models import Gallery

def photo_list(request, gallery_slug, *args, **kwargs):
    try:
        gallery = Gallery.objects.get(slug=gallery_slug)
    except Gallery.DoesNotExist:
        raise Http404

    kwargs[‘queryset’] = gallery.photo_set.all()

    if not kwargs.has_key(‘extra_context’):
        kwargs[‘extra_context’] = {}
    kwargs[‘extra_context’].update({‘gallery’: gallery})

    return object_list(request, *args, **kwargs)

The django database api allows to get the “QuerySet” of the related model using the “photo_set” attribute, which is passed to the generic “object_list” view as extra argument. I didn’t add the “object_detail” generic views because I am using the ThickBox javascript widget to show photos directly from the photo listing pages.

Urls

This is the “urls.py” file for the gallery app:

from django.conf.urls.defaults import *
from django.views.generic.list_detail import object_list
from tagging.views import tagged_object_list

from views import photo_list
from models import Gallery, Photo

gallery_list_dict = {
    ‘queryset’: Gallery.objects.all(),
    ‘template_object_name’: ‘gallery’,
}

photo_list_dict = {
    ‘template_object_name’: ‘photo’,
}

tags_dict = {
    ‘model’: Photo,
    ‘template_name’: ‘gallery/tagged_photo_list.html’,
}

urlpatterns = patterns(”,
    (r’^$’, object_list, gallery_list_dict),
    (r’^gallery/(?P<gallery_slug>[-\w]+)/$’, photo_list, photo_list_dict),
    (r’^(?P<tag>\w+)/$’, tagged_object_list, tags_dict),
)

Add the following url configuration to your project “urls.py”:

urlpatterns = patterns(”,
    … CUT …
    (r’^photos/’, include(‘myproject.gallery.urls’)),
    … CUT …
)

You may need to change the prefix of your “urlpatterns” to fit your needs.

Templates

“base_gallery.html”

{% extends “base.html” %}

{% block htmlhead %}
<link rel=”stylesheet” href=”{{ media_url }}css/thickbox.css” type=”text/css” media=”screen” />
<script type=”text/javascript” src=”{{ media_url }}js/jquery.js”></script>
<script type=”text/javascript” src=”{{ media_url }}js/jquery.thickbox.js”></script>
{% endblock %}

{% block title %}Photo Gallery{% endblock %}

{% block headtitle %}Photo Gallery{% endblock %}

{% block content %}
{% endblock %}

“gallery/gallery_thumbnail.html”

{% load image_filters %}
<div class=”thumbnail”>
{% if gallery.thumb %}
<p>
    <a href=”{{ gallery.get_absolute_url }}” title=”{{ gallery }}”><img src=”{{ gallery.thumb|thumb:”width=120” }}” alt=”{{ gallery }}” /></a>
</p>
{% endif %}
<p>
    <a href=”{{ gallery.get_absolute_url }}” title=”{{ gallery }}”>{{ gallery }}
</a>
</p>
</div>

“gallery/photo_thumbnail.html”

{% load image_filters %}
<div class=”thumbnail”>
<p>
    <a href=”{{ media_url }}{{ photo.image }}” title=”{{ photo.title }}” class=”thickbox” rel=”photo-gallery”><img src=”{{ photo.image|thumb:”width=120” }}” alt=”{{ photo.title }}” /></a>
</p>
<p>
Gallery: <a href=”{{ photo.gallery.get_absolute_url }}” title=”{{ photo.gallery }}”>{{ photo.gallery }}</a><br />
{% if photo.tags %}Tags: {{ photo.tags }}<br />{% endif %}
</p>
</div>

“gallery/gallery_list.html”

{% extends “base_gallery.html” %}

{% block content %}
{% for gallery in gallery_list %}
    {% include “gallery/gallery_thumbnail.html” %}
{% endfor %}
{% endblock %}

“gallery/photo_list.html”

{% extends “base_gallery.html” %}

{% block title %}Photo Gallery: {{ gallery }}{% endblock %}
{% block headtitle %}Photo Gallery: {{ gallery }}{% endblock %}

{% block content %}
{% for photo in photo_list %}
    {% include “gallery/photo_thumbnail.html” %}
{% endfor %}
{% endblock %}

“gallery/tagged_photo_list”

{% extends “base_gallery.html” %}

{% block title %}Gallery photos tagged with &quot;{{ tag }}&quot;{% endblock %}
{% block headtitle %}Gallery photos tagged with &quot;{{ tag }}&quot;{% endblock %}

{% block content %}
{% for photo in object_list %}
    {% include “gallery/photo_thumbnail.html” %}
{% endfor %}
{% endblock %}

That’s all. Please let me know if you have any question and if you find any mistake, I really appreciate your feedback.

Add to: Add to deliciousAdd to DiggAdd to FurlAdd to redditAdd to YahooAdd to NewsvineAdd to Spurl

Tags: django gallery tutorial


Site updates: Django based photo gallery

Posted July 27, 2007, 4:41 p.m.

I’ve added a photo gallery to the website, obviously it’s django-powered :) and uses ThickBox for displaying images.

I have done it very quickly and surely in the next days I will publish a tutorial to show how it works.

Add to: Add to deliciousAdd to DiggAdd to FurlAdd to redditAdd to YahooAdd to NewsvineAdd to Spurl

Tags: gallery thickbox jquery


Babel integration in django

Posted July 16, 2007, 2:50 a.m.

Few months ago I looked for i18n data collections and I found WeBDA. It’s used by Satchmo and it could be easily integrated with other django projects.

I looked also at Babel and I wrote a simple middleware class that allows to have locale data collections available accessing the LOCALE attribute of request objects:

import babel

try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local

_thread_locals = local()

def get_current_locale():
    “””
    Get current locale data outside views.
    See http://babel.edgewall.org/wiki/ApiDocs/babel.core for Locale
    objects documentation
    “””
    return getattr(_thread_locals, ‘locale’, None)

class BabelMiddleware(object):
    “””
    This is a very simple middleware that uses
    babel (http://babel.edgewall.org) for accessing locale
    data in request objects through request.LOCALE attribute
    “””
    def process_request(self, request):
        try:
            locale = babel.Locale.parse(request.LANGUAGE_CODE, sep=’-‘)
        except (ValueError, babel.UnknownLocaleError):
            pass
        else:
            _thread_locals.locale = locale
            setattr(request, ‘LOCALE’, locale)

The get_current_locale function allows also to access locale data outside application views. This middleware configuration must be placed after the ‘django.middleware.locale.LocaleMiddleware’ MIDDLEWARE_CLASSES setting.

MIDDLEWARE_CLASSES = (
    … cut …
    ‘django.middleware.locale.LocaleMiddleware’,
    ‘middleware.locale.BabelMiddleware’,
    … cut …
)

Add to: Add to deliciousAdd to DiggAdd to FurlAdd to redditAdd to YahooAdd to NewsvineAdd to Spurl

Tags: i18n l10n django babel internationalization localization

0 comments


django-tagging cloud template tag

Posted March 28, 2007, 8:17 p.m.

I added tagging functionality to this site using the great django-tagging application.

Reading the models.py source I found the “cloud_from_model” method into the TagManager model manager, useful for delicious-style tag clouds and I used for writing this simple template tag.

from django.db.models import get_model
from django.template import Library, Node, TemplateSyntaxError
from apps.tagging.models import Tag

register = Library()

class TagsCloudForModelNode(Node):
    def __init__(self, model, varname, step):
        self.varname, self.step = varname, step
        self.model = get_model(*model.split(‘.’))

    def render(self, context):
        context[self.varname] = Tag.objects.cloud_for_model(self.model,
                                                            self.step)
        return ”

def do_tags_cloud_for_model(parser, token):
    “””
    Retrieves a tag cloud for the given model

    Example usage::

        {% tags_cloud_for_model articles.Article as object_list %}
        {% tags_cloud_for_model articles.Article as object_list step 6 %}
    “””
    step = 4
    bits = token.contents.split()
    if len(bits) < 4:
        raise TemplateSyntaxError(‘%s tag requires three arguments’ % bits[0])
    if bits[2] != ‘as’:
        raise TemplateSyntaxError(“second argument to %s tag must be ‘as’” % bits[0])
    if len(bits) > 4:
        if bits[4] != ‘step’:
            raise TemplateSyntaxError(“optional fourth argument to %s tag must be ‘step’” % bits[0])
        try:
            step = int(bits[5])
        except IndexError:
            raise TemplateSyntaxError(“optional fifth argument after step is required”)
        except ValueError:
            raise TemplateSyntaxError(“optional fifth argument after step is not an integer”)
    return TagsCloudForModelNode(bits[1], bits[3], step)

register.tag(‘tags_cloud_for_model’, do_tags_cloud_for_model)

I reduced a lot the code in the views, I hope it could be useful to somebody.

Add to: Add to deliciousAdd to DiggAdd to FurlAdd to redditAdd to YahooAdd to NewsvineAdd to Spurl

Tags: django tagging template


django-096-released

Posted March 23, 2007, 2:03 p.m.

I’m happy to see that the 0.96 version of the Django was finally released!

One of the most interesting feature is newforms, a replacement for the django.forms library that will be removed in the next releases.

Now form objects are not tied into the database models, you will have less code to write in the views and into templates.

It is also easy to subclass Form, Widget and Field objects, allowing a very high level of customization. Have fun!

http://www.djangoproject.com/weblog/2007/mar/23/096/

http://www.djangoproject.com/documentation/newforms/

Add to: Add to deliciousAdd to DiggAdd to FurlAdd to redditAdd to YahooAdd to NewsvineAdd to Spurl

Tags: django newforms

Archive

Meta

Python

A Django site.

Hosting by Webfaction

Creative Commons License

View Massimo Scamarcia's profile on LinkedIn

Ads