-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7dd045f
Showing
53 changed files
with
2,821 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
*.pyc | ||
*.pyo | ||
.installed.cfg | ||
bin | ||
develop-eggs | ||
dist | ||
downloads | ||
eggs | ||
parts | ||
src/*.egg-info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Copyright (c) Dominik Szopa. | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without modification, | ||
are permitted provided that the following conditions are met: | ||
|
||
1. Redistributions of source code must retain the above copyright notice, | ||
this list of conditions and the following disclaimer. | ||
|
||
2. Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
|
||
3. Neither the name of django-template-repl nor the names of its contributors may be used | ||
to endorse or promote products derived from this software without | ||
specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
include LICENSE | ||
include README.txt | ||
include HISTORY.txt | ||
recursive-include src/moderation/templates * | ||
recursive-include src/moderation/fixtures * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
Introduction | ||
============ | ||
|
||
django-moderation is reusable application for Django framework, that allows to | ||
moderate any model objects. | ||
|
||
Possible use cases: | ||
|
||
- User creates his profile, profile is not visible on site. | ||
It will be visible on site when moderator approves it. | ||
- User change his profile, old profile data is visible on site. | ||
New data will be visible on site when moderator approves it. | ||
|
||
Features: | ||
|
||
- configurable admin integration(data changed in admin can be visible on | ||
site when moderator approves it) | ||
- moderation queue in admin | ||
- html differences of changes between versions of objects | ||
- configurable email notifications | ||
- custom model form that allows to edit changed data of object | ||
- 100% PEP8 correct code | ||
- test coverage > 80% | ||
|
||
|
||
Requirements | ||
============ | ||
|
||
python >= 2.4 | ||
|
||
django >= 1.1 | ||
|
||
|
||
Installation | ||
=========== | ||
|
||
Download source code from http://github.com/dominno/django-moderation and run installation script: | ||
|
||
$> python setup.py install | ||
|
||
|
||
Configuration | ||
============= | ||
|
||
1. Add to your INSTALLED_APPS in your settings.py: | ||
|
||
``moderation`` | ||
2. Run command ``manage.py syncdb`` | ||
3. Register Models with moderation | ||
|
||
from django.db import models | ||
import moderation | ||
|
||
|
||
class YourModel(models.Model): | ||
pass | ||
|
||
moderation.register(YourModel) | ||
|
||
4. Register admin class with your Model | ||
|
||
from django.contrib import admin | ||
from moderation.admin import ModerationAdmin | ||
|
||
|
||
class YourModelAdmin(ModerationAdmin): | ||
"""Admin settings go here.""" | ||
|
||
admin.site.register(YourModel, YourModelAdmin) | ||
|
||
If you want to disable integration of moderation in admin, | ||
add admin_intergration_enabled = False to your admin class: | ||
|
||
class YourModelAdmin(ModerationAdmin): | ||
admin_intergration_enabled = False | ||
|
||
admin.site.register(YourModel, YourModelAdmin) | ||
|
||
|
||
How django-moderation works | ||
=========================== | ||
|
||
When you change existing object or create new one, it will not be publicly | ||
available until moderator approves it. It will be stored in ModeratedObject model. | ||
|
||
your_model = YourModel(description='test') | ||
your_model.save() | ||
|
||
YourModel.objects.get(pk=your_model.pk) | ||
Traceback (most recent call last): | ||
DoesNotExist: YourModel matching query does not exist. | ||
|
||
When you will approve object, then it will be publicly available. | ||
|
||
your_model.moderated_object.approve(moderatated_by=user, | ||
reason='Reason for approve') | ||
|
||
YourModel.objects.get(pk=1) | ||
<YourModel: YourModel object> | ||
|
||
You can access changed object by calling changed_object on moderated_object: | ||
|
||
your_model.moderated_object.changed_object | ||
<YourModel: YourModel object> | ||
|
||
This is deserialized version of object that was changed. | ||
|
||
Now when you will change an object, old version of it will be available publicly, | ||
new version will be saved in moderated_object | ||
|
||
your_model.description = 'New description' | ||
your_model.save() | ||
|
||
your_model = YourModel.objects.get(pk=1) | ||
your_model.__dict__ | ||
{'id': 1, 'description': 'test'} | ||
|
||
your_model.moderated_object.changed_object.__dict__ | ||
{'id': 1, 'description': 'New description'} | ||
|
||
your_model.moderated_object.approve(moderatated_by=user, | ||
reason='Reason for approve') | ||
|
||
your_model = YourModel.objects.get(pk=1) | ||
your_model.__dict__ | ||
{'id': 1, 'description': 'New description'} | ||
|
||
Email notifications | ||
=================== | ||
|
||
By default when user change object that is under moderation, | ||
e-mail notification is send to moderator. It will inform him | ||
that object was changed and need to be moderated. | ||
|
||
When moderator approves or reject object changes then e-mail | ||
notification is send to user that changed this object. It will | ||
inform user if his changes were accepted or rejected and inform him | ||
why it was rejected or approved. | ||
|
||
How to overwrite email notification templates | ||
--------------------------------------------- | ||
|
||
E-mail notifications use following templates: | ||
|
||
- moderation/notification_subject_moderator.txt | ||
- moderation/notification_message_moderator.txt | ||
- moderation/notification_subject_user.txt | ||
- moderation/notification_message_user.txt | ||
|
||
Default context: | ||
|
||
``content_type`` - content type object of moderated object | ||
``moderated_object`` - ModeratedObject instance | ||
``site`` - current Site instance | ||
|
||
|
||
How to pass extra context to email notification templates | ||
--------------------------------------------------------- | ||
|
||
If you want to pass extra context to email notification methods | ||
you new need to create new class that subclass BaseModerationNotification class. | ||
|
||
class CustomModerationNotification(BaseModerationNotification): | ||
def inform_moderator(self, | ||
subject_template='moderation/notification_subject_moderator.txt', | ||
message_template='moderation/notification_message_moderator.txt', | ||
extra_context=None): | ||
'''Send notification to moderator''' | ||
extra_context={'test':'test'} | ||
super(CustomModerationNotification, self).inform_moderator(subject_template, | ||
message_template, | ||
extra_context) | ||
|
||
def inform_user(self, user, | ||
subject_template='moderation/notification_subject_user.txt', | ||
message_template='moderation/notification_message_user.txt', | ||
extra_context=None) | ||
'''Send notification to user when object is approved or rejected''' | ||
extra_context={'test':'test'} | ||
super(CustomModerationNotification, self).inform_user(user, | ||
subject_template, | ||
message_template, | ||
extra_context) | ||
|
||
|
||
Next register it with moderation as notification_class: | ||
|
||
moderation.register(YourModel, notification_class=CustomModerationNotification) | ||
|
||
|
||
|
||
Signals | ||
======= | ||
|
||
``moderation.signals.pre_moderation`` - signal send before object is approved or rejected | ||
|
||
Arguments sent with this signal: | ||
|
||
``sender`` | ||
The model class. | ||
``instance`` | ||
Instance of model class that is moderated | ||
``status`` | ||
Moderation status, 0 - rejected, 1 - approved | ||
|
||
|
||
``moderation.signals.post_moderation`` - signal send after object is approved or rejected | ||
|
||
Arguments sent with this signal: | ||
|
||
``sender`` | ||
The model class. | ||
``instance`` | ||
Instance of model class that is moderated | ||
``status`` | ||
Moderation status, 0 - rejected, 1 - approved | ||
|
||
|
||
Forms | ||
===== | ||
|
||
When creating ModelForms for models that are under moderation use | ||
BaseModeratedObjectForm class as ModelForm class. Thanks to that form will initialized | ||
with data from changed_object. | ||
|
||
from moderation.forms import BaseModeratedObjectForm | ||
|
||
|
||
class ModeratedObjectForm(BaseModeratedObjectForm): | ||
|
||
class Meta: | ||
model = MyModel | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#!/usr/bin/env python | ||
############################################################################## | ||
# | ||
# Copyright (c) 2006 Zope Corporation and Contributors. | ||
# All Rights Reserved. | ||
# | ||
# This software is subject to the provisions of the Zope Public License, | ||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. | ||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | ||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | ||
# FOR A PARTICULAR PURPOSE. | ||
# | ||
############################################################################## | ||
"""Bootstrap a buildout-based project | ||
Simply run this script in a directory containing a buildout.cfg. | ||
The script accepts buildout command-line options, so you can | ||
use the -c option to specify an alternate configuration file. | ||
$Id$ | ||
""" | ||
|
||
import os, shutil, sys, tempfile, urllib2 | ||
|
||
tmpeggs = tempfile.mkdtemp() | ||
|
||
is_jython = sys.platform.startswith('java') | ||
|
||
try: | ||
import pkg_resources | ||
except ImportError: | ||
ez = {} | ||
exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' | ||
).read() in ez | ||
ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) | ||
|
||
import pkg_resources | ||
|
||
if sys.platform == 'win32': | ||
def quote(c): | ||
if ' ' in c: | ||
return '"%s"' % c # work around spawn lamosity on windows | ||
else: | ||
return c | ||
else: | ||
def quote (c): | ||
return c | ||
|
||
cmd = 'from setuptools.command.easy_install import main; main()' | ||
ws = pkg_resources.working_set | ||
|
||
if is_jython: | ||
import subprocess | ||
|
||
assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd', | ||
quote(tmpeggs), 'zc.buildout'], | ||
env=dict(os.environ, | ||
PYTHONPATH= | ||
ws.find(pkg_resources.Requirement.parse('setuptools')).location | ||
), | ||
).wait() == 0 | ||
|
||
else: | ||
assert os.spawnle( | ||
os.P_WAIT, sys.executable, quote (sys.executable), | ||
'-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout', | ||
dict(os.environ, | ||
PYTHONPATH= | ||
ws.find(pkg_resources.Requirement.parse('setuptools')).location | ||
), | ||
) == 0 | ||
|
||
ws.add_entry(tmpeggs) | ||
ws.require('zc.buildout') | ||
import zc.buildout.buildout | ||
zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap']) | ||
shutil.rmtree(tmpeggs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
[buildout] | ||
parts = python django-1.1 | ||
develop = . | ||
eggs = | ||
django-moderation | ||
ipdb | ||
pep8 | ||
django-test-extensions | ||
figleaf | ||
django-mailer | ||
|
||
|
||
|
||
[python] | ||
recipe = zc.recipe.egg | ||
interpreter = python | ||
eggs = ${buildout:eggs} | ||
|
||
[django-1.1] | ||
recipe = djangorecipe | ||
version = 1.1.1 | ||
projectegg = example_project | ||
project = example_project | ||
test = moderation | ||
testrunner = test-1.1 | ||
eggs = ${buildout:eggs} |
Oops, something went wrong.