Prevents users from overwriting each others changes in Django.
Django Admin Locking is tested in the following environments
- Python (2.7, 3.4)
- Django (1.6, 1.7, 1.8, 1.9, 1.10)
Add 'locking'
to your INSTALLED_APPS
setting.
INSTALLED_APPS = (
...
'locking',
)
Add the required URL pattern:
url(r'^locking/', include('locking.urls')),
To enable locking for a ModelAdmin
:
from django.contrib import admin
from locking.admin import LockingAdminMixin
from my_project.mt_models import MyModel
class MyModelAdmin(LockingAdminMixin, admin.ModelAdmin):
pass
admin.site.register(MyModel, MyModelAdmin)
The LockingAdminMixin
will automatically add a new column that displays which rows are currently locked. To manually place this column add is_locked
to the admin's list_display
property.
Locking Admin offers the following variables for customization in your settings.py
:
LOCKING_EXPIRATION_SECONDS
- Time in seconds that an object will stay locked for without a 'ping' from the server. Defaults to180
.LOCKING_PING_SECONDS
- Time in seconds between 'pings' to the server with a request to maintain or gain a lock on the current form. Defaults to15
.LOCKING_SHARE_ADMIN_JQUERY
- Should locking use instance of jQuery used by the admin or should it use it's own bundled version of jQuery? Useful because older versions of Django do not come with a new enough version of jQuery for admin locking. Defaults toTrue
.LOCKING_DB_TABLE
- Used to override the default locking table name (locking_lock
)LOCKING_DELETE_TIMEOUT_SECONDS
- If not zero, locks will not be deleted immediately when a user leaves an admin form, but will instead be set to expire in the specified number of seconds. Specifying this setting can help avoid the following situation: a user hits 'save and continue' on a form, causing the page to reload. If locks are deleted instantly, someone else might grab the lock before the form loads again. If this value is specified, it should be set to the approximate time it takes a form to save (generally a few seconds). Defaults to0
.
Overtime, you may find it necessary to remove expired locks from the database. This can be done with the following management command
$ python manage.py delete_expired_locks
If you have a non-zero specified for LOCKING_DELETE_TIMEOUT_SECONDS
in your settings, you should setup a reoccurring Cron or Celery task to automatically run this management command on a regular interval.
Running the included test suite requires the following additional requirements:
- Selenium
- PhantomJS
By default, form field widgets are disabled by adding the attribute disabled = disabled
to all inputs
. If you are using a custom widget, such as a WYSIWYG editor, you may need to register a locking plugin to ensure it is correctly locked and unlocked.
Plugin registration takes the following form:
window.locking.LockingFormPlugins.register({
'enable': function(form) { /* Enabled my custom widget */ },
'disable': function(form) { /* Disable my custom widget */ }
})
For an example, look at the included plugin for the CKEditor WYSIYG editor.
This app is compatible the popular admin theme django-grappelli
This code is licensed under the Simplified BSD License. View the LICENSE file under the root directory for complete license and copyright information.