Source code for werewolf.admin

__title__ = 'werewolf.admin'
__version__ = '0.4'
__build__ = 0x000004
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
__all__ = ('WerewolfBaseAdmin',)

from functools import partial

from django.contrib import admin
from django import forms
from django.forms.models import modelform_factory
from django.contrib.admin.util import flatten_fieldsets

from werewolf.utils import status_choices_for_user
from werewolf.triggers import registry
from werewolf.settings import USE_DJANGO_REVERSION, DEFAULT_STATUS

if USE_DJANGO_REVERSION:
    from reversion.admin import VersionAdmin
    AdminParentClass = VersionAdmin
else:
    AdminParentClass = admin.ModelAdmin

[docs]class WerewolfBaseAdmin(AdminParentClass): """ Base werewolf admin model. :property list werewolf_protected_fields: List of fields to protect in form of the following tuple (``field_name``, ``required_permission``). """ werewolf_protected_fields = []
[docs] def formfield_for_dbfield(self, db_field, **kwargs): """ Here we replace the choices based on the user permissions. """ if 'status' == db_field.name: status_choices = status_choices_for_user(kwargs['request'].user, self.model._meta.app_label) field = forms.ChoiceField(choices=status_choices, required=True, initial=DEFAULT_STATUS) return field return super(WerewolfBaseAdmin, self).formfield_for_dbfield(db_field, **kwargs)
[docs] def queryset(self, request): """ Make sure users with no rights to edit an object with status, don't even see it. """ status_choices = dict(status_choices_for_user(request.user, self.model._meta.app_label)).keys() return super(WerewolfBaseAdmin, self).queryset(request).filter(status__in=status_choices)
[docs] def status_change_trigger(self, request, obj, form, change): """ Status change trigger. Executes appropriate registered trigger if applicable. :param django.http.HttpRequest request: :param django.db.models.Model obj: Subclass of ``django.db.models.Model``. :param form: :param bool change: """ # It's important to perform the checks after the if 'status' in form.changed_data: Trigger = registry.get_for_model(obj, obj.status) if Trigger: trigger = Trigger(obj=obj, request=request) trigger.process()
[docs] def save_model(self, request, obj, form, change): super(WerewolfBaseAdmin, self).save_model(request, obj, form, change) self.status_change_trigger(request, obj, form, change)
[docs] def get_form(self, request, obj=None, **kwargs): """ Hiding fields that non-authorised users should not have access to. It's done based on the ``werewolf_protected_fields`` of your ``ModelAdmin``. But if happen to override that method for your own needs, make sure the it also reflects the django-werewolf concepts. """ if not self.werewolf_protected_fields: return super(WerewolfBaseAdmin, self).get_form(request=request, obj=obj, **kwargs) # Hiding fields that non-authorised users should not have access to. if self.declared_fieldsets: fields = flatten_fieldsets(self.declared_fieldsets) else: fields = None if self.exclude is None: exclude = [] else: exclude = list(self.exclude) exclude.extend(self.get_readonly_fields(request, obj)) if self.exclude is None and hasattr(self.form, '_meta') and self.form._meta.exclude: # Take the custom ModelForm's Meta.exclude into account only if the # ModelAdmin doesn't define its own. exclude.extend(self.form._meta.exclude) # if exclude is an empty list we pass None to be consistant with the # default on modelform_factory exclude = exclude or [] for field_name, required_permission in self.werewolf_protected_fields: if not request.user.has_perm('{0}.{1}'.format(self.model._meta.app_label, required_permission)): exclude.append(field_name) exclude = exclude or None defaults = { "form": self.form, "fields": fields, "exclude": exclude, "formfield_callback": partial(self.formfield_for_dbfield, request=request), } defaults.update(kwargs) return modelform_factory(self.model, **defaults)
[docs] def get_changelist_formset(self, request, **kwargs): """ Removes protected fields from the list_editiable field list. """ if self.werewolf_protected_fields: self.list_editable = list(self.list_editable) # convert to a list so we can 'remove()' for field_name, required_permission in self.werewolf_protected_fields: # Remove field from the list_editable list if permissions are not granted. if not request.user.has_perm('{0}.{1}'.format(self.model._meta.app_label, required_permission)): try: self.list_editable.remove(field_name) except: pass return super(WerewolfBaseAdmin, self).get_changelist_formset(request, **kwargs)
[docs] def get_fieldsets(self, request, obj=None): """ Hiding fields that non-authorised users should not have access to. It's done based on the ``werewolf_protected_fields`` of your ``ModelAdmin``. But if happen to override that method for your own needs, make sure the it also reflects the django-werewolf concepts. """ fieldsets = super(WerewolfBaseAdmin, self).get_fieldsets(request, obj=None) if not self.werewolf_protected_fields: return fieldsets cleaned_fieldsets = [] for fieldset_label, fieldset in fieldsets: fields = list(fieldset['fields']) for field_name, required_permission in self.werewolf_protected_fields: # Cleaning the field that has been already excluded from form (in ``get_form``). if not request.user.has_perm('{0}.{1}'.format(self.model._meta.app_label, required_permission)): try: fields.remove(field_name) except: pass fieldset_attributes = { 'fields': fields, 'classes': fieldset.get('classes', list()) } cleaned_fieldsets.append((fieldset_label, fieldset_attributes)) return cleaned_fieldsets
Read the Docs v: latest
Versions
latest
Downloads
PDF
HTML
Epub
On Read the Docs
Project Home
Builds

Free document hosting provided by Read the Docs.