Files
postgres-web/pgweb/util/admin.py
2018-04-15 14:09:06 -04:00

126 lines
4.6 KiB
Python

from django.contrib import admin
from django.conf import settings
from pgweb.core.models import ModerationNotification
from pgweb.mailqueue.util import send_simple_mail
class PgwebAdmin(admin.ModelAdmin):
"""
ModelAdmin wrapper that will enable a few pg specific things:
* Markdown preview for markdown capable textfields (specified by
including them in a class variable named markdown_capable that is a tuple
of field names)
* Add an admin field for "notification", that can be sent to the submitter
of an item to inform them of moderation issues.
"""
change_form_template = 'admin/change_form_pgweb.html'
def formfield_for_dbfield(self, db_field, **kwargs):
fld = admin.ModelAdmin.formfield_for_dbfield(self, db_field, **kwargs)
if hasattr(self.model, 'markdown_fields'):
if db_field.name in self.model.markdown_fields:
fld.widget.attrs['class'] = fld.widget.attrs['class'] + ' markdown_preview'
return fld
def change_view(self, request, object_id, form_url='', extra_context=None):
if hasattr(self.model, 'send_notification') and self.model.send_notification:
# Anything that sends notification supports manual notifications
if extra_context == None:
extra_context = dict()
extra_context['notifications'] = ModerationNotification.objects.filter(objecttype=self.model.__name__, objectid=object_id).order_by('date')
return super(PgwebAdmin, self).change_view(request, object_id, form_url, extra_context)
# Remove the builtin delete_selected action, so it doesn't
# conflict with the custom one.
def get_actions(self, request):
actions = super(PgwebAdmin, self).get_actions(request)
del actions['delete_selected']
return actions
# Define a custom delete_selected action. This is required because the
# default one uses the delete functionality in QuerySet, which bypasses
# the delete() operation on the model, and thus won't send out our
# notifications. Manually calling delete() on each one will be slightly
# slower, but will send proper notifications - and it's not like this
# is something that happens often enough that we care about performance.
def custom_delete_selected(self, request, queryset):
for x in queryset:
x.delete()
custom_delete_selected.short_description = "Delete selected items"
actions=['custom_delete_selected']
def save_model(self, request, obj, form, change):
if change and hasattr(self.model, 'send_notification') and self.model.send_notification:
# We only do processing if something changed, not when adding
# a new object.
if request.POST.has_key('new_notification') and request.POST['new_notification']:
# Need to send off a new notification. We'll also store
# it in the database for future reference, of course.
if not obj.org.email:
# Should not happen because we remove the form field. Thus
# a hard exception is ok.
raise Exception("Organisation does not have an email, canot send notification!")
n = ModerationNotification()
n.objecttype = obj.__class__.__name__
n.objectid = obj.id
n.text = request.POST['new_notification']
n.author = request.user.username
n.save()
# Now send an email too
msgstr = _get_notification_text(obj,
request.POST['new_notification'])
send_simple_mail(settings.NOTIFICATION_FROM,
obj.org.email,
"postgresql.org moderation notification",
msgstr)
# Also generate a mail to the moderators
send_simple_mail(settings.NOTIFICATION_FROM,
settings.NOTIFICATION_EMAIL,
"Moderation comment on %s %s" % (obj.__class__._meta.verbose_name, obj.id),
_get_moderator_notification_text(obj,
request.POST['new_notification'],
request.user.username
))
# Either no notifications, or done with notifications
super(PgwebAdmin, self).save_model(request, obj, form, change)
def register_pgwebadmin(model):
admin.site.register(model, PgwebAdmin)
def _get_notification_text(obj, txt):
objtype = obj.__class__._meta.verbose_name
return """You recently submitted a %s to postgresql.org.
During moderation, this item has received comments that need to be
addressed before it can be approved. The comment given by the moderator is:
%s
Please go to https://www.postgresql.org/account/ and make any changes
request, and your submission will be re-moderated.
""" % (objtype, txt)
def _get_moderator_notification_text(obj, txt, moderator):
return """Moderator %s made a comment to a pending object:
Object type: %s
Object id: %s
Comment: %s
""" % (moderator,
obj.__class__._meta.verbose_name,
obj.id,
txt,
)