|
| 1 | +Django Concurrency |
| 2 | +================== |
| 3 | + |
| 4 | + |
| 5 | +[](https://badge.fury.io/py/django-concurrency) |
| 6 | +[](https://codecov.io/github/saxix/django-concurrency?branch=develop) |
| 7 | +[](https://github.com/saxix/django-concurrency/actions/workflows/tests.yaml) |
| 8 | +[](http://django-concurrency.readthedocs.io/en/stable/) |
| 9 | + |
| 10 | + |
| 11 | +django-concurrency is an [optimistic lock][1] implementation for Django. |
| 12 | + |
| 13 | +It prevents users from doing concurrent editing in Django both from UI and from a |
| 14 | +django command. |
| 15 | + |
| 16 | + |
| 17 | +How it works |
| 18 | +------------ |
| 19 | + |
| 20 | +```python |
| 21 | + |
| 22 | +from django.db import models |
| 23 | +from concurrency.fields import IntegerVersionField |
| 24 | + |
| 25 | +class ConcurrentModel( models.Model ): |
| 26 | + version = IntegerVersionField( ) |
| 27 | + name = models.CharField(max_length=100) |
| 28 | +``` |
| 29 | + |
| 30 | +Now if you try:: |
| 31 | + |
| 32 | +```python |
| 33 | + |
| 34 | +a = ConcurrentModel.objects.get(pk=1) |
| 35 | +a.name = '1' |
| 36 | + |
| 37 | +b = ConcurrentModel.objects.get(pk=1) |
| 38 | +b.name = '2' |
| 39 | + |
| 40 | +a.save() |
| 41 | +b.save() |
| 42 | + |
| 43 | +``` |
| 44 | + |
| 45 | +you will get a ``RecordModifiedError`` on ``b.save()`` |
| 46 | + |
| 47 | + |
| 48 | +Similar projects |
| 49 | +---------------- |
| 50 | + |
| 51 | +Other projects that handle concurrent editing are [django-optimistic-lock][10] |
| 52 | +and [django-locking][11] anyway concurrency is "a batteries included" optimistic |
| 53 | +lock management system, here some features not available elsewhere: |
| 54 | + |
| 55 | + * can be applied to any model; not only your code (ie. django.contrib.auth.Group) |
| 56 | + * handle [list-editable][2] ChangeList. (handle `#11313 <https://code.djangoproject.com/ticket/11313>`_) |
| 57 | + * manage concurrency conflicts in admin's actions |
| 58 | + * can intercept changes performend out of the django app (ie using pgAdmin, phpMyAdmin, Toads) (using [TriggerVersionField][6]) |
| 59 | + * can be disabled if needed (see [disable_concurrency][3]) |
| 60 | + * [ConditionalVersionField][4] to handle complex business rules |
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | +Project Links |
| 65 | +------------ |
| 66 | + |
| 67 | +- Code: https://github.com/saxix/django-concurrency |
| 68 | +- Documentation: https://django-concurrency.readthedocs.org/en/latest/ |
| 69 | +- Issue Tracker: https://github.com/saxix/django-concurrency/issues |
| 70 | +- Download Package: http://pypi.python.org/pypi/django-concurrency/ |
| 71 | + |
| 72 | + |
| 73 | +[10]:https://github.com/gavinwahl/django-optimistic-lock |
| 74 | +[11]:https://github.com/stdbrouw/django-locking |
| 75 | +[1]:http://en.wikipedia.org/wiki/Optimistic_concurrency_control |
| 76 | +[2]:https://django-concurrency.readthedocs.org/en/latest/admin.html#list-editable |
| 77 | +[3]:https://django-concurrency.readthedocs.org/en/latest/api.html?#disable-concurrency |
| 78 | +[4]:https://django-concurrency.readthedocs.org/en/latest/fields.html#conditionalversionfield |
| 79 | +[6]:https://django-concurrency.readthedocs.org/en/latest/fields.html#triggerversionfield |
0 commit comments