YUJI TOMITA

Tech Consultant. Backend Developer. Frontend Developer. Designer. Adventure Time Super Fan.

Tag: Django

Django 1.4 Alpha – Custom List Filter : RIP FilterSpec

Finally, it’s here in django trunk!

Easy to use custom List Filters (previously known as FilterSpecs)!

This ticket has always around for a while awaiting documentation and tests: thank you so much to julien for making it happen.

https://code.djangoproject.com/ticket/5833

This works like a charm.

Here’s the example straight out of the brand new docs on trunk:

from django.utils.translation import ugettext_lazy as _
from django.contrib.admin import SimpleListFilter

class DecadeBornListFilter(SimpleListFilter):
   # Human-readable title which will be displayed in the
   # right admin sidebar just above the filter options.
   title = _('decade born')

   # Parameter for the filter that will be used in the URL query.
   parameter_name = 'decade'

   def lookups(self, request, model_admin):
       """
       Returns a list of tuples. The first element in each
       tuple is the coded value for the option that will
       appear in the URL query. The second element is the
       human-readable name for the option that will appear
       in the right sidebar.
       """
       return (
           ('80s', _('in the eighties')),
           ('90s', _('in the nineties')),
       )

   def queryset(self, request, queryset):
       """
       Returns the filtered queryset based on the value
       provided in the query string and retrievable via
       `self.value()`.
       """
       # Compare the requested value (either '80s' or 'other')
       # to decide how to filter the queryset.
       if self.value() == '80s':
           return queryset.filter(birthday__year__gte=1980,
                                   birthday__year__lte=1989)
       if self.value() == '90s':
           return queryset.filter(birthday__year__gte=1990,
                                  birthday__year__lte=1999)

class PersonAdmin(ModelAdmin):
   list_filter = (DecadeBornListFilter,)

Django — Proxy Model ContentTypes are not created

Proxy model ContentType objects are not automatically created, causing problems if you want to give users permission to add/change/delete your proxy models.

Thanks to Mark Haus for a simple fix to connect to the post_syncdb signal to generate contenttypes by name.

Source: http://dev.markhaus.com/blog/2011/04/django-setting-the-right-permissions-associated-with-proxy-models/


from django.db.models import get_models
from django.db.models.signals import post_syncdb
from django.utils.encoding import smart_unicode

from django.contrib.auth.management import create_permissions, _get_all_permissions

# Hack the postsyncdb signal, so we can fix the misbehavior of the
# content_type
# assignment to the proxy models.
# see http://code.djangoproject.com/ticket/11154

def create_permissions_respecting_proxy(
    app, created_models, verbosity, **kwargs
    ):
    if not kwargs['sender'].__name__ == 'myproject.myapp.models':
        # if not in 'customer' app, then use the original function
        create_permissions(app, created_models, verbosity, **kwargs)
        return

    from django.contrib.contenttypes.models import ContentType
    from django.contrib.auth import models as auth_app
    app_models = get_models(app)
    searched_perms = list()
    ctypes = set()
    for klass in app_models:
        # this is where the difference is: the original create_permissions
        # use ctype = ContentType.objects.get_for_model(klass)
        opts = klass._meta
        ctype, created = ContentType.objects.get_or_create(
            app_label=opts.app_label,
            model=opts.object_name.lower(),
            defaults = {'name': smart_unicode(opts.verbose_name_raw)}
            )
        # end of the modification
        ctypes.add(ctype)
        for perm in _get_all_permissions(klass._meta):
            searched_perms.append((ctype, perm))

    all_perms = set(auth_app.Permission.objects.filter(
            content_type__in=ctypes
            ).values_list("content_type", "codename"))

    for ctype, (codename, name) in searched_perms:
        if(ctype.pk, codename) in all_perms:
            continue
        p = auth_app.Permission.objects.create(
            codename=codename, name=name, content_type=ctype
            )
        if verbosity >=2:
            print "Adding permission '%s'" % p


post_syncdb.disconnect(
    create_permissions,
    dispatch_uid='django.contrib.auth.management.create_permissions',
    )

post_syncdb.connect(
    create_permissions_respecting_proxy,
    dispatch_uid='django.contrib.auth.management.create_permissions',
    )

Python / Django — MIME Type Content Type

I just used the mimetypes python standard library to guess filetypes via file names.

It assumes the user followed naming conventions and does not attempt to read the data.

Django / Nginx — Making SSL Work on Django Behind a Reverse Proxy & HTTP Only Apache

Update: django 1.4 has a new feature that allows you to specify which HTTP header implies SSL via a new setting SECURE_PROXY_SSL_HEADER, but it comes with dire warnings that your front end proxy MUST strip this header if not secure so that the user can not set the header manually to imply an SSL secure connection.

I didn’t think of this, and it’s a great point… my example did not explicitly set the flag OFF if not on port 443.

https://docs.djangoproject.com/en/1.4/ref/settings/#secure-proxy-ssl-header

How to make SSL work on Django when the certification is done on the front-end proxy server & apache is only listening on http.

I have nginx working as a reverse proxy for Apache / mod_python serving Django, somewhat according to the instructions here:

http://lethain.com/entry/2007/jul/17/dreamier-dream-server-nginx/

Basically, Nginx sits in the front, and forwards all requests but /media/ to apache.

My problem arose when I wanted to implement this SSL Redirect middleware: http://www.djangosnippets.org/snippets/880/

The setup, and why the middleware loops infinitely

I have nginx dealing with the SSL, forwarding requests to the same apache vhost as regular http, so apache is blissfully unaware of SSL.

This means request.is_secure() always returns False, which means the SSLRedirect middleware endlessly loops around a redirect because is_secure keeps returning False.

The fix

Add some extra header to the request in Nginx that specifies an HTTPS connection

To fix the problem I just set up my nginx to add a header “HTTP_X_FORWARDED_PROTOCOL” = “https”

Next, I replaced the request.is_secure() in the SSLRedirect middleware with a check to first see if the above mentioned header is in request.META, and then if its value is ‘https’. Return true if that is the case, and we successfully get a redirect.

Edit the SSLRedirectMiddleware

Edit the middleware to check for our secure header.

You must edit the above mentioned snippet somewhere in the _is_secure(self, request): definition.

Modify to:

def _is_secure(self, request):
     if request.is_secure():
         return True

     if 'HTTP_X_FORWARDED_PROTOCOL' in request.META:
         return True

Edit nginx conf

Edit nginx.conf (mine lives in /etc/nginx/nginx.conf) wherever you have your nginx listening on port 443.

Add a the custom header to your configuration where you have your other headers set (right inside the location brackets).

    proxy_set_header X-Forwarded-Protocol https;

Restart and you’re done!

Restart nginx and apache and you are good to go.

Django — Django Sniff / Django Sniffit / DjangoSniffit.org

So just now on IRC somebody was suggesting “DjangoSniffer” (was referring to djangosnippets.org but djangosnippets is so blatantly obvious & impossible to forget, that nobody questioned it) which lead to a correction: “DjangoSniff”? which lead to me searching django+sniff on google, and #1 result was: http://www.flickr.com/photos/jacqamoe/2382980232/

Django the cat, sniffing something. :D

Django — List all fields in an Object

The last extremely simple post about “How to get the object instance primary key in Django” reminded me of something.

Listing all model fields in a django model instance

for field in model_instance._meta.fields:
    print field.name

model_instance._meta.get_field('field_name') # if you want one field    

Listing all attributes in a python object

Similarly, ever have a random object that you don’t know the fields of?
Or ever not remember whether your field/method/attribute was called short_description or shortdescription?

Use the built in dir() function.

dir(model_instance)

Django — Get an objects Primary Key

Somebody asked on #Django IRC: what is an easy way to get an objects primary key? I was shocked to hear he couldn’t find it on google.. and I guess it’s true. This is probably the very first stepping stone in learning Django.

I say: Do the Django Tutorials, they are short, well written, and fun!
Besides, its got a hassle-free return policy (90 days).

Well, uh…
object_instance.id = your primary key

Wait… I was wrong. here’s an update from SmileyChris:

Actually, object_instance.pk would be more correct. “id” is just the default primary key field, whereas “pk” is an alias to the field which is defined as the primary key.

Django — Attaching arbitrary data to anonymous sessions.

Often times it’s necessary to have data stored PER user. A perfect example of this (and my particular problem) is/was a shopping cart: the core of any e-commerce site.

How do we do that? One of the problems is that the users in question are anonymous users. If they were registered users, we could easily take request.user and identify them that way. For anonymous users, we need cookies to identify who’s who.

Luckily Django automatically generates nice cookies that ID the user in a secure fashion (not anything like: logged_in=1) so most of the work is done.

Basically, request.session is a mutable dictionary. Fantastic!

That means you can literally do something like this:
request.session['Arbitrary'] = 'This is Arbitrary Data'

and retrieve it any time you wish in the same fashion:

data = request.session['Arbitrary']

This is useful for a shopping cart because you can create a cart, and put its ID in request.session to know which user session it belongs to.

like so:
newcart = Cart()
request.session['shopping_cart'] = newcart.id

and every time you need to access a users cart request.session['shopping_cart']identifies the cart they are using!

Note: You would have write a statement so that a new cart is created if request.session['cart'] is blank. You should have a check in place to do that. If not request.session['shopping_cart'], create cart, else get cart.

This clearly isn’t limited to shopping carts though… Cool stuff.

Duplicate Key IntegrityError Django

If you are wondering what part of your Django model is wrong because it is spitting out a nameless IntegrityError, it might be this:

I had a model with Unique=True & Blank=True that caused description-less IntegrityErrors because with two objects that have a field ” (blank), or Null, it was no longer unique.

I wanted the field to be Unique, IF and only if it was not blank or null.

I’ll just use Blank=True, null=True and let it be not unique if it ever does.

Follow

Get every new post delivered to your Inbox.

Join 95 other followers