#!/usr/bin/env python # -*- coding: utf-8 - # # # Look here: https://bitbucket.org/depaolim/optlock # The snippet of Marco De Paoli is much better than this one! :-) # # # # @contact: marcoberi@gmail.com # @version: 1.0 # @license: MIT http://www.opensource.org/licenses/mit-license.php # from django.db import models, connection from django.utils.translation import ugettext as _ from django.contrib import admin class ExceptionNewVersionInDb(Exception): def __init__(self, obj, version, code=None, params=None): from django.utils.encoding import force_unicode self.message = force_unicode("{0} ver {1}: {2}".format(unicode(obj), version, _("saved by another user"))) def __str__(self): return repr(self.message) def __repr__(self): return 'ExceptionNewVersionInDb(%s)' % repr(self.message) class Model(models.Model): _version_opt_lock = models.IntegerField( blank = True, null = True, default = 0, verbose_name = _("Version")) def get_version_in_db(self): if self.pk: cursor = connection.cursor() raw_query = 'select _version_opt_lock from "{0}" where "{1}" = '.format( self._meta.db_table, self._meta.pk.attname) cursor.execute(raw_query + "%s", (self.pk,)) retval = cursor.fetchone() return retval[0] return 0 def save(self, *args, **kw_args): if self.pk: version_in_db = self.get_version_in_db() if self._version_opt_lock != version_in_db: raise ExceptionNewVersionInDb(self, version_in_db) self._version_opt_lock = version_in_db + 1 else: self._version_opt_lock = 1 super(Model, self).save(*args, **kw_args) class Meta: abstract = True class ModelAdmin(admin.ModelAdmin): def formfield_for_dbfield(self, db_field, *args, **kwargs): formfield = super(ModelAdmin, self).formfield_for_dbfield(db_field, *args, **kwargs) if (db_field.name == "_version_opt_lock"): formfield.widget.attrs["readonly"] = "readonly" return formfield