- Artur Barseghyan (firstname.lastname@example.org)
To make a notification system for editors to avoid editing same content simultaneously.
- We have one generic model multiedit.models.MultiEditLog, that holds
- django.contrib.auth.models.User objects;
- information about first- and last-pings of users;
- django.contrib.contenttypes.models.ContentType object to make the app to work with ANY kind of Django objects.
See the docs of multiedit.models.MultiEditLog model and multiedit.managers.MultiEditLogManager for more information.
We never insert a new record for the group (content_type, object_id, user_id). We update the existing one. When entering an article we first try to find such a record in the list of "active" editors. If we try to update its' last_pinged value with datetime.datetime.now(). If no records updated, we try to update just the list of editors for the given object, but unlike previous time, we update both first_pinged and last_pinged fields by setting their values to datetime.datetime.now(). If second query does not affect any records, it means we have a fresh (first time ever) login, so we create one. By following these steps, we guarantee that we won't have garbage in the system! So, when we need to find out a new "master" (user who started editing the object first), we get the list of active users from which we select the one who had entered the live view first (fist_pinged field).
- We have a manager for multiedit.models.MultiEditLog model to perform various operations.
=> See the multiedit.manager.MultiEditLogManager module.
=> See the multiedit.views.ping view.
Next to that, we have a widget (which is very easy to use) for rendering the view (so that in our model, we would only use the existing code).
=> See the multiedit.utils.render_multiedit_widget function.
As an AJAX driven view, we will be sending an AJAX request every N seconds (configurable in settings in variable MULTIEDIT_PING_INTERVAL).
Nobody has the article opened for editing and new user is entering. We check the MultiEditLog table with the following request: get all active users for the article who has been pinged as active within last 2 minutes. If nobody did that, we first:
- We become the master for the article.
- On the top of the page, where the "Currently edited by" area will be displayed, we list all other active editors (those who entered the article edit screen since we started to edit it). Beware, that in case of lost connection the rights of the "master" are regained by the user, who had entered the article next.
- We do show the user's status next to his name in the list above ("masters" will be clearly identified).
Criteria for being a master: The active user (last pinged was made less than a minute ago minutes) for the article given who has the very first record in MultiEditLog model made for the article.
- Install multiedit by:
pip install -e hg+http://bitbucket.org/barseghyanartur/django-multiedit#egg=multiedit
Add 'multiedit' to your INSTALLED_APPS in the global settings.py.
Override app settings in your global settings.py (see the multiedit.defaults for the list of settings). As for now, most important of those are:
- Add the following lines to the global urls.py file.
# MultiEdit URLs (r'^multiedit/', include('multiedit.urls')),
./manage.py syncdb # database synchronization
- USAGE AND EXAMPLES
For making it simpler, I have made a working example of a demo. Just set the value of MULTIEDIT_SHOW_ADMIN_TEST_MODEL_DEMO to True in local_settings, restart the server and you have a working demo.
In short, you need to go through the following steps to activate the app for your model. * In your models.py (see multiedit.models for examples, as we have tests there):
- You either inherit your model from multiedit.models.MultiEditBaseModel
- from multiedit.models import MultiEditBaseModel class MyTestModel(MultiEditBaseModel)
- ...or define a method within your model
from multiedit.models import MultiEditLog from multiedit.utils import render_multiedit_widget def multiedit_widget(self):
""" Example of multi edit widget implementation. """ return render_multiedit_widget(MultiEditLog, self)
multiedit_widget.allow_tags = True multiedit_widget.short_description = _('Active editors list')
- In admin.py (see multiedit.admin for examples, as we have tests there):
- In the admin class of your model
- readonly_fields = ('multiedit_widget',)
Simple, isn't it? That's all.
- In general, this app is well tested. See "multiedit.tests" and "multiedit.management.commands.multiedit_tests" modules for examples.
- Write even better docs.