{"id":13813941,"url":"https://github.com/theatlantic/django-locking","last_synced_at":"2025-05-15T01:32:19.487Z","repository":{"id":1301272,"uuid":"1243437","full_name":"theatlantic/django-locking","owner":"theatlantic","description":"Prevents users from doing concurrent editing in Django. Works out of the box in the admin interface, or you can integrate it with your own apps using a public API.","archived":false,"fork":true,"pushed_at":"2018-11-29T23:00:47.000Z","size":1005,"stargazers_count":17,"open_issues_count":3,"forks_count":11,"subscribers_count":22,"default_branch":"v2","last_synced_at":"2024-08-04T04:04:55.768Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://stdbrouw.github.com/django-locking/","language":"Python","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"debrouwere/django-locking","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theatlantic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-01-11T22:35:53.000Z","updated_at":"2024-08-04T04:04:55.769Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/theatlantic/django-locking","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theatlantic%2Fdjango-locking","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theatlantic%2Fdjango-locking/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theatlantic%2Fdjango-locking/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theatlantic%2Fdjango-locking/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theatlantic","download_url":"https://codeload.github.com/theatlantic/django-locking/tar.gz/refs/heads/v2","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225319403,"owners_count":17455766,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T04:01:37.404Z","updated_at":"2024-11-19T08:31:16.610Z","avatar_url":"https://github.com/theatlantic.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"=======================================\nConcurrency control with django-locking\n=======================================\n\nDjango has seen great adoption in the content management sphere, especially among the newspaper crowd. One of the trickier things to get right, is to make sure that nobody steps on each others toes while editing and modifying existing content. Newspaper editors might not always be aware of what other editors are up to, and this goes double for distributed teams. When different people work on the same content, the one who saves last will win the day, while the other edits are overwritten.\n\n`django-locking` provides a system that makes concurrent editing impossible, and informs users of what other users are working on and for how long that content will remain locked. Users can still read locked content, but cannot modify or save it.\n\n``django-locking`` makes sure no two users can edit the same content at the same time, preventing annoying overwrites and lost time. Find the repository and download the code at http://github.com/stdbrouw/django-locking\n\n``django-locking`` has only been tested on Django 1.2 and 1.3, but probably works from 1.0 onwards.\n\nDocumentation\n-------------\nForked from the Django Locking plugin at stdbrouw/django-locking, this code features the cream of the crop for django-locking combining features from over 4 repos!\n\nNew features added to this fork\n===============================\nChanges on change list pages\n----------------------------\n    \nUnlock content object from change list page by simply clicking on the lock icon\n_______________________________________________________________________________\n\n![unlock prompt](https://github.com/RobCombs/django-locking/raw/master/docs/screenshots/unlock_prompt.png)\n\nHover over the lock icon to see when the lock expires\n_____________________________________________________\n\n![expire status](https://github.com/RobCombs/django-locking/raw/master/docs/screenshots/expire_status.png)\n\nHover over the username by the lock icon to see the full name of the person who has locked the content object \n_____________________________________________________________________________________________________________\n\n![lock_by_who](https://github.com/RobCombs/django-locking/raw/master/docs/screenshots/lock_by_who.png)\n\n\nConsolidated username and lock icon into one column on change list page\nChanges in settings:\n----------------------------\n\nAdded Lock warning and expiration flags in terms of seconds\n\nLock messages:\n----------------------------\n\nAdded options to reload or save the object when lock expiration message is shown\n\n![reload or bust](https://github.com/RobCombs/django-locking/raw/master/docs/screenshots/reload_or_bust.png)\n\nImproved look and feel for the lock messages\nLock messages fade in and out seamlessly\nAdded much more detail to let users know who the content object was locked by providing the username, first name and last name\nAdded lock expiration warnings\nShows how much longer the object is locked for in minutes\n\nLocking:\n----------------------------\n\n Added hard locking support using Django's validation framework\n\n![hard lock](https://github.com/RobCombs/django-locking/raw/master/docs/screenshots/hard_lock.png)\n\n Set hard and soft locking as the default to ensure the integrity of locking\n Added seamless unlocking when lock expires\n\n![auto unlock](https://github.com/RobCombs/django-locking/raw/master/docs/screenshots/auto_unlock.png)\n\n\nArchitecture:\n----------------------------\n\n1 model tracks lock information and that's it!  No messy migrations for each model that needs locking.\nRefactored and cleaned up code for easier maintainability\n Simplified installation by coupling common functionality into base admin/form/model classes\n\n\n10 Minute Install\n-----------------\n\n1) Get the code:\n\n    git clone git@github.com:RobCombs/django-locking.git\n\n2) Install the django-locking python egg:\n    \n    cd django-locking\n    sudo python setup.py install\n\n3) Add locking to the list of INSTALLED_APPS in project settings file:\n\n    INSTALLED_APPS = ('locking',)\n    \n4) Add the following url mapping to your urls.py file:\n\n    urlpatterns = patterns('',\n    (r'^admin/ajax/', include('locking.urls')),\n    )\n\n5) Add locking to the admin files that you want locking for:\n\n    from locking.admin import LockableAdmin\n    class YourAdmin(LockableAdmin):\n       list_display = ('get_lock_for_admin')\n\n6) Add warning and expiration time outs to your Django settings file:\n\n    LOCKING = {'time_until_expiration': 120, 'time_until_warning': 60}\n\n\n7) Build the Lock table in the database:\n\n    django-admin.py/manage.py migrate locking (For south users. Recommended approach) OR\n    django-admin.py/manage.py syncdb (For non south users)\n\n8) Install django-locking media:\n\n    cp -r django-locking/locking/media/locking $your static media directory\n\nNote: This is the step where people usually get lost.  \nJust start up your django server and look for the 200/304s http responses when the server attempts to load the media \nas you navigate to a model change list/view page where you've enabled django-locking. If you see 404s, you put the media in the wrong directory! \n\nYou should see something like this in the django server console:\n\n[02/May/2012 15:33:20] \"GET /media/static/locking/css/locking.css HTTP/1.1\" 304 0\n\n[02/May/2012 15:33:20] \"GET /media/static/web/common/javascript/jquery-1.4.4.min.js HTTP/1.1\" 304 0\n\n[02/May/2012 15:33:20] \"GET /media/static/locking/js/jquery.url.packed.js HTTP/1.1\" 304 0\n\n[02/May/2012 15:33:21] \"GET /admin/ajax/variables.js HTTP/1.1\" 200 114\n\n[02/May/2012 15:33:21] \"GET /media/static/locking/js/admin.locking.js?v=1 HTTP/1.1\" 304 0\n\n[02/May/2012 15:33:21] \"GET /admin/ajax/redirects/medleyobjectredirect/14/is_locked/?_=1335987201245 HTTP/1.1\" 200 0\n\n[02/May/2012 15:33:21] \"GET /admin/ajax/redirects/medleyobjectredirect/14/lock/?_=1335987201295 HTTP/1.1\" 200 0\n\n\nYou can also hit the media directly for troubleshooting your django-locking media installation: \nhttp://www.local.wsbradio.com:8000/media/static/locking/js/admin.locking.js\nIf the url resolves, then you've completed this step correctly!  \nBasically, the code refers to the media like so.  That's why you needed to do this step.\n\n    class Media:\n    js = ( 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js', \n         'static/locking/js/jquery.url.packed.js',\n         \"/admin/ajax/variables.js\",\n         \"static/locking/js/admin.locking.js?v=1\")\n    css = {\"all\": (\"static/locking/css/locking.css\",)\n    }\n\nThat's it!\n\nChecking the installation\n-------------------------\nSimulate a lock situation -\u003e Open 2 browsers and hit your admin site with one user logged into the 1st browser and\nother user logged into the other.  Go to the model in the admin that you've installed locking for with one browser.  \nOn the other browser, go to the change list/change view pages of the model that you've installed django-locking for.\nYou'll see locks in the interface similar to the screen shots above.\n\nYou can also look at your server console and you'll see the client making ajax calls to the django server checking for locks like so:\n\n    [04/May/2012 15:15:09] \"GET /admin/ajax/redirects/medleyobjectredirect/14/is_locked/?_=1336158909826 HTTP/1.1\" 200 0\n    [04/May/2012 15:15:09] \"GET /admin/ajax/redirects/medleyobjectredirect/14/lock/?_=1336158909858 HTTP/1.1\" 200 0\n\nOptional\n--------\nIf you'd like to enforce hard locking(locking at the database level), then add the LockingForm class to the same admin pages\n\nExample:\n\n    from locking.forms import LockingForm\n    class YourAdmin(LockableAdmin):\n     list_display = ('get_lock_for_admin')\n     form = LockingForm\n     \nNote: if you have an existing form and clean method, then call super to invoke the LockingForm's clean method\n\nExample:\n\n    from locking.forms import LockingForm\n    class YourFormForm(LockingForm):\n      def clean(self):\n        self.cleaned_data = super(MedleyRedirectForm, self).clean()\n        ...some code\n        return self.cleaned_data\n\nCREDIT\n------\nThis code is basically a composition of the following repos with a taste of detailed descretion from me. Credit goes out to the following authors and repos for their contributions\nand my job for funding this project:\nhttps://github.com/stdbrouw/django-locking\nhttps://github.com/runekaagaard/django-locking\nhttps://github.com/theatlantic/django-locking\nhttps://github.com/ortsed/django-locking","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheatlantic%2Fdjango-locking","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheatlantic%2Fdjango-locking","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheatlantic%2Fdjango-locking/lists"}