Looking for a Django Admin Page Lock? We've got you covered

One of the main projects that my team is responsible for is Showmax’s CMS (Content Management System), where we manage content metadata for our streaming platform through their browsers. The CMS is used by multiple users in five different countries, so we needed a way to prevent them from stepping on each others’ toes while attempting to edit the same content simultaneously. This article gives some insights into the solution we developed and some of our learnings. We’ve open sourced the solution in the hope we help anyone else facing this kind of challenge, and we’re definitely keen to get some ideas and feedback.

We started writing the CMS as a plain Django application and we had a page locking mechanism in place almost from the beginning. Two years ago we started rewriting pieces of the project into Django Admin, but our existing page locking tooling was not Django Admin compatible. So we had to rewrite it to bring the page locking functionality to the migrated pages. Since Showmax likes to share useful stuff with the open-source community, we have decided to publish our work on GitHub.

The concept of page lock is nothing new. You want to make sure that only one user can edit one object in the CMS at any given time. It is also necessary to implement timeouts, so that inactive users are kicked out from the page after a certain period of time to prevent them from blocking edits forever. At the same time, the users need a way of prolonging their session so that you don’t kick them out just before they finish their work. We also wanted to give some visibility and control over the page lock to the users, so we decided to add a bar with controls to every page using the locking feature.

Status bar showing that the signed in user is holding the lock for the next 30 minutes

To start using the page locking feature, you first need to install the application from PyPI and enable it in your project’s settings.py. Then edit your base template used for Django Admin pages and add a block which takes care of rendering the controls bar, as described in the documentation. For each Django Admin page where you want to enable the page locking, make the view inherit from PageLockAdminMixin class.

To distinguish between objects, we use page URLs. You can choose to disregard query parameters by setting the PAGE_LOCK_URL_IGNORE_PARAMETERS option in settings.py. to True. There are a lot of other configuration options available, which you might want to go through and tune according to your needs. One of the most useful ones would probably be PAGE_LOCK_DISABLE, which allows developers to temporarily disable the page locking on their local workstation during development. By default, Django’s configured database will be used for persisting the locks. Alternatively you can use Redis as the storage backend.

When a user tries to access a page which is currently locked, they will see all editing fields as disabled and they will not be able to save the page. This is achieved by removing the edit permission for the given page from the user, so Django Admin can take care of the rest. Additionally, you can completely hide certain parts of the locked pages by adding a page_lock_block CSS class to any element in the template.

Communication between the locking application and the browser is performed via HTTP API. When you enable the application, it adds a couple of additional URLs, which the client-side JavaScript talks to in order to read the lock state, acquire and eventually release it. Please take this into consideration during deployment, as you might want to prevent public access to these URLs.

We hope you will find the page locking application useful. We will appreciate any feedback or contributions, as there is still a lot of things to do to improve.

Fork

Please check the original version of this article at