So I found myself in a situation where I needed to have multilingual support for the DB in Django. i18n does a great job for static messages, but what about all that dynamic data, ie. news in multiple languages. Sure you could create a column per language you want to support but that’s an awful waste on the table, plus when you want to start supporting additional languages you have to alter the table to add columns — not a best, and definetly not the most user friendly way.

Another way around the problem is to create separate table for each table that requires multilingual fields. Every translation table would have a ForeignKey to the parent table and consist of all the fields that need to be in a specific language plus either a field or ForeignKey to a table that has the language code (for queries/identification which language is used).

I’ve created   django-multilingual-model  to do just that and make it easier to use/query such tables.

Here’s an example:

Python [Show Plain Code]:
  1. #
  2.     class Language(models.Model):
  3.         code = models.CharField(max_length=5)
  4.         name = models.CharField(max_length=16)
  5.  
  6.     class BookTranslation(models.Model):
  7.         language = models.ForeignKey("Language")
  8.         title = models.CharField(max_length=32)
  9.         description = models.TextField()
  10.         model = models.ForeignKey("Book")
  11.  
  12.     class Book(MultilingualModel):
  13.         ISBN = models.IntegerField()
  14.  
  15.         class Meta:
  16.             translation = BookTranslation
  17.             multilingual = [‘title’, ‘description’]
  18.  
  19.     lang_en = Language(code="en", name="English")
  20.     lang_en.save()
  21.     lang_pl = Language(code="pl", name="Polish")
  22.     book = Book(ISBN="1234567890")
  23.     book.save()
  24.     book_en = BookTranslation()
  25.     book_en.title = "Django for Dummies"
  26.     book_en.description = "Django described in simple words."
  27.     book_en.model = book
  28.     book_en.save()
  29.     book_pl = BookTranslation()
  30.     book_pl.title = "Django dla Idiotow"
  31.     book_pl.description = "Django opisane w prostych slowach"
  32.     book_pl.model = book
  33.     book_pl.save()
  34.  
  35.     # now here comes the magic
  36.     book.title_en
  37.     u‘Django for Dummies’
  38.     book.description_pl
  39.     u‘Django opisane w prostych slowach’

It is a common need to have per-row (instance) permissions in a web application.

I’ve created a very simple and non intrusive module to help with that.

You can find the source code of the django-granular-permissions on Google Code here:

http://code.google.com/p/django-granular-permissions/

It’s fully functional, only thing missing are unittests and templatetag that would use the request.user provided by the session middleware context.

To use the package simply add it somewhere to your PYTHONPATH (ie. under your django project, or use

easy_install -U django-granular-permissions

to grab it from cheeseshop) and add the ‘django_granular_permissions’ to your INSTALLED_APPS in your projects settings.py

That’s it. From now on you can check, add and remove permissions for any instance of models class in your project like this:

Python [Show Plain Code]:
  1. # adding permission ‘edit’ to a user ‘Bart’ on an instance of a MyObject from myapp.models
  2.  from django.contrib.auth.models import User, Group
  3.  from myapp.models import MyObject
  4.  user = User.objects.get(username=‘Bart’)
  5.  obj = MyObject()
  6.  obj.save()
  7.  user.add_row_perm(obj, ‘edit’)
  8.  user.has_row_perm(obj, ‘edit’)
  9. True
  10.  user.has_row_perm(obj, ‘delete’)
  11. False
  12.  
  13. # similar for groups
  14.  group = Group.objects.get(pk=1) # get first group in the db
  15.  group.add_row_perm(obj, ‘read’)
  16.  
  17. # now we’ll add the user to the group and he will inherit the ‘read’ permission
  18.  user.groups.add(group)
  19.  user.has_row_perm(obj, ‘read’)
  20. True
  21.  
  22. # now to remove permission
  23.  user.del_row_perm(obj, ‘edit’)
  24.  user.has_row_perm(obj, ‘edit’)
  25. False
  26.  
  27. # note that when you try to remove a permission from a user that is granted to him through group nothing changes
  28.  user.del_row_perm(obj, ‘read’)
  29.  user.has_row_perm(obj, ‘read’)
  30. True