NinjaCipher:-*-:ro60

Archive for the ‘django’ Category

New Django Paginator Example

Monday, August 4th, 2008

So I pulled the latest Django codebase from svn today and I noticed that my old pagination setup no longer works. Not really surprising as a ton of stuff is being updated due to the coming release of 1.0. So I did a bit of digging into the new pagination code to see if I could rework my wrapper class to work with the new release. It turns out that with the updates there really is no good reason to wrap the classes any more. They have done a good job of working out all the kinks in the pagination setup and it does everything I need it to do out of the box.

So here is a quick nutshell example of how I am using the new django.core.paginator classes to replace the old ObjectPaginator wrapper from my previous example.

in your view:

from django.core.paginator import Paginator

#create a new paginator instance by passing it a collection of objects and the per page count
paginator = Paginator(Contact.objects.all().order_by('last_name'), 10)

#get the page number from a get param
#if param is blank then set page to 1
page = int(request.GET.get('page', '1'))

#grab the current page from the paginator...
contacts = paginator.page(page)

#render the template and pass the contacts page into the template
return render_to_response('contacts.html',{'contacts':contacts})

in your template:

{% for contact in contacts.object_list %}
{{ contact.name }}
{% endfor %}

I’d say that’s pretty easy. Here is a link to a simple snippet that you can use to create a paging footer.

Notice to get the page of pages info all you have to do is output the page object like so… {{ contacts }} . Pretty cool.

group_required decorator

Friday, June 20th, 2008

Here is a decorator that I came up with to augment the already available login_required and permission_required decorators. This one takes a group name and makes sure the logged in user is a part of it.

def group_required(group_name, login_url='/accounts/login/'):
    def wrap(view_func):
        def in_group(request, *args, **kwargs):
            from django.contrib.auth.models import Group
            try:
                group = request.user.groups.get(name=group_name)
            except Group.DoesNotExist:
                from django.http import HttpResponseRedirect
                return HttpResponseRedirect(login_url)
            else:
                return view_func(request, *args, **kwargs)

        return in_group
    return wrap

to use

@group_required('groupies')
def index(request):
   ...

I’m posting this with a disclaimer up front. Every time I post what I think is a clever snippet someone always tells me that I am reinventing the wheel and it already exists in django. So if this is another case of me being tragically uninformed then please let me know as I would most likely use the official way instead.

Adding InnoDB to sqlall output

Sunday, March 23rd, 2008

Have you ever wondered why you can’t have manage.py sqlall output your create table statements as InnoDB tables for mysql? Well I have. I always go in and update the statements by hand to add that after the fact. So I did a bit of pokeing around and figured out a hack to add in a settings flag so you can set the table type that your manage.py will use for its create table statements.

There are 2 changes you need to make. First off you need to add the following setting in your settings.py

DATABASE_TABLE_ENGINE = 'InnoDB'

the other part is an update to the django.core.management.sql file. This file is really long (even though the actual hack is short). Basically the update is adding the following code in the many_to_many_sql_for_model and sql_model_create functions.

try:
   if settings.DATABASE_TABLE_ENGINE != None:
      table_output.append('ENGINE=%s' % settings.DATABASE_TABLE_ENGINE)
except:
   pass

It’s really pretty basic but personally I find it useful. Now (here comes the disclaimer) I can’t guarantee that there isn’t already a way to do this. Despite all my digging I didn’t find it if it does exist. Also I’m sure there is a better way to add this update then going in and hacking the core script (or even if that’s playing nice and submitting an enhancement ticket which I should really read up on). On that note I would suggest not just swapping out the download version for your version. It would prob be best to just use my version as a guide to show you how to update your own sql.py so you don’t run into any file version probs. Just for the sake of clarity I’m running django svn trunk version 6898.

Edit I noticed my local django version was pretty damn old so I just updated to 7353. The hack still seems to be working fine. End Edit

You can download a copy of my hacked sql.py here: updated django.core.management.sql . As always use at your own risk and let me know what could be done better.

Edit I’m adding a svn diff as well for those of you who would rather see only the changes: download diffEnd Edit

django template wrapper helper

Sunday, March 9th, 2008

edit:
# ericflo pointed out something that I totally forgot about… render_to_string. And he’s completely correct… It does exactly the same thing and most likely does it better… DOH! Well whatever… here is my version anyway ;)

—————————
Here is a handy little helper I cooked up for dynamically loading dynamic content into a reusable template wrapper. It takes the path of a template and a dict of vars to populate, compiles the template and returns the resulting value as a string. You can then pass in the resulting variable into your main context. Pretty simple but very useful.

def wrap_content(template, var_dict):
    from django.template import Context, loader
    c = Context(var_dict)
    t = loader.get_template(template)
    return t.render(c)

called like so

mod = wrap_content('shared/mod_wrapper.html',{'title':'test title','content':'content test',})