Created
May 26, 2017 12:53
-
-
Save frague59/f90ba63bb2548fb27e32576329159543 to your computer and use it in GitHub Desktop.
people admin
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
# -*- coding: utf-8 -*- | |
""" | |
:class:`directory.models.people.People` admin for :mod:`directory` application | |
:creationdate: 14/11/16 13:52 | |
:moduleauthor: François GUÉRIN <fguerin@ville-tourcoing.fr> | |
:modulename: directory.admin.people | |
""" | |
from __future__ import unicode_literals | |
import logging | |
from django.conf import settings | |
from django.contrib import messages | |
from django.contrib.auth import models as a_models | |
from django.http import HttpResponse | |
from django.template.loader import render_to_string | |
from django.utils.safestring import mark_safe | |
from django.utils.translation import ugettext_lazy as _ | |
from guardian.admin import GuardedModelAdminMixin | |
from guardian.shortcuts import get_objects_for_user | |
from import_export.admin import ImportExportMixin | |
from reversion.admin import VersionAdmin | |
from unidecode import unidecode | |
from directory.admin import utilities, list_filters, forms, resources | |
from directory.idcards import IdCardGenerator | |
from directory.models import people, perms, hierarchy | |
__author__ = 'fguerin' | |
logger = logging.getLogger('directory.admin.people') | |
#: Session administrated hierarchies identifier | |
SESSION_ADMINISTRATED_HIERARCHIES = 'ADMINISTRATED_HIERARCHIES' | |
class PeopleAdmin(ImportExportMixin, utilities.AdministrableAdminMixin, GuardedModelAdminMixin, VersionAdmin): | |
""" | |
Administrate :class:`directory.models.people.People` instances | |
""" | |
# Import / Export | |
resource_class = resources.PeopleResource | |
skip_admin_log = False | |
# Common admin attributes | |
actions = ['action_create_idcards', | |
'action_delete_idcards', | |
'action_mutate', ] | |
list_display = ['full_name', 'rendered_hierarchy', | |
'job', 'email', 'phone', 'image_thumb', | |
'idcard', 'display_image'] | |
list_editable = ['display_image', ] | |
list_display_links = ['full_name'] | |
list_filter = ['civility', | |
'job', | |
list_filters.AdditionalRolePeoplesListFilter, | |
list_filters.PeopleHierarchiesListFilter, | |
list_filters.PeopleHierarchiesStrictListFilter, | |
list_filters.ImagePeoplesListFilter, | |
list_filters.IdCardPeoplesListFilter] | |
search_fields = ('last_name', 'usage_name', 'first_name', 'hierarchy__name', 'job__label',) | |
form = forms.PeopleAdminForm | |
def get_queryset(self, request): | |
""" | |
Gets the administrable :class:`directory.models.people.People` items | |
:param request: Http Request | |
:returns: QuerySet of administrable :class:`directory.models.people.People` items | |
""" | |
queryset = get_objects_for_user(request.user, | |
perms=[perms.PERM_CHANGE_PEOPLE, perms.PERM_CREATE_IDCARD_PEOPLE], | |
klass=people.People, any_perm=True) | |
queryset = (queryset | |
.exclude(hierarchy=utilities.get_mutation_hierarchy(request)) | |
.select_related('civility', 'hierarchy', 'user_author', 'user_updater', 'image', 'job') | |
.prefetch_related('additional_role')) | |
return queryset | |
def get_fieldsets(self, request, obj=None): | |
if request.user.is_superuser: | |
fieldsets= ((_('Identification'), {'fields': ['civility', 'last_name', 'usage_name', | |
'first_name', 'image', 'display_image']}), | |
(_('Position'), {'fields': ('hierarchy', 'job', 'comment', 'is_chief', 'additional_role')}), | |
(_('Id card'), {'fields': ('idcard_guid', 'idcard_date',), # 'idcard_signed', | |
'description': _('Professional Id card are documents given to each agents in the ' | |
'collectivity. This card is required to access to the city hall and ' | |
'to all the municipal buildings. It is used to identify agents.'), | |
'classes': ('grp-collapse',)}), | |
utilities.DATE_IN_OUT_FIELDSET, | |
utilities.CONTACTABLE_FIELDSET,) | |
else: | |
fieldsets = ((_('Identification'), {'fields': ['civility', 'last_name', 'usage_name', | |
'first_name', 'display_image']}), | |
(_('Position'), {'fields': ('hierarchy', 'job', 'comment', 'is_chief', 'additional_role')}), | |
(_('Id card'), {'fields': ('idcard_guid', 'idcard_date',), # 'idcard_signed', | |
'description': _('Professional Id card are documents given to each agents in the ' | |
'collectivity. This card is required to access to the city hall and ' | |
'to all the municipal buildings. It is used to identify agents.'), | |
'classes': ('grp-collapse',)}), | |
utilities.DATE_IN_OUT_FIELDSET, | |
utilities.CONTACTABLE_FIELDSET,) | |
return fieldsets | |
@staticmethod | |
def _get_administrated_hierarchies(request): | |
""" | |
Gets the administrated hierarchies for the current connected user, from session if available, else from db. | |
:param request: HTTP Request | |
:returns: administrated hierarchies | |
""" | |
hierarchies = request.session.get(SESSION_ADMINISTRATED_HIERARCHIES, None) | |
if hierarchies is not None: | |
logger.debug('PeopleAdmin::_get_administrated_hierarchies() from session : len(hierarchies) = %d', | |
len(hierarchies)) | |
return hierarchies | |
else: | |
hierarchies = get_objects_for_user(request.user, perms=perms.PERM_CHANGE_HIERARCHY, | |
klass=hierarchy.Hierarchy) | |
logger.debug('PeopleAdmin::_get_administrated_hierarchies() from db : len(hierarchies) = %d', | |
len(hierarchies)) | |
# Saves the administrated hierarchies into the session | |
request.session[SESSION_ADMINISTRATED_HIERARCHIES] = hierarchies | |
return hierarchies | |
def formfield_for_foreignkey(self, db_field, request=None, **kwargs): | |
if db_field.name == 'hierarchy' and not request.user.is_superuser: | |
hierarchies = self._get_administrated_hierarchies(request) | |
kwargs['queryset'] = hierarchies | |
return super(PeopleAdmin, self).formfield_for_foreignkey(db_field=db_field, request=request, **kwargs) | |
def get_form(self, request, obj=None, **kwargs): | |
""" | |
Gets the update / create form for a given object | |
.. note:: | |
This methods diverts the ``form.clean`` method for super admins to ``clean_superuser`` method | |
:param request: Http request | |
:param obj: current object | |
:param kwargs: Additional keyword arguments | |
:returns: form | |
""" | |
# Change form class based on user | |
if request.user.is_superuser: | |
self.form = forms.PeopleAdminForm | |
else: | |
self.form = forms.EditorPeopleAdminForm | |
# Builds the form | |
form = super(PeopleAdmin, self).get_form(request, obj, **kwargs) | |
return form | |
def has_change_permission(self, request, obj=None): | |
""" | |
Checks whether the connected user has permission to change current instance | |
:param request: HTTP request | |
:param obj: current instance | |
:returns: True if user is allowed, False otherwise | |
""" | |
# Gets the connected user | |
user = request.user | |
if user.is_superuser: | |
return True | |
if obj is not None: | |
return user.has_perm(perms.PERM_CHANGE_PEOPLE, obj) | |
allowed = (perms.is_editor(user) and get_objects_for_user(user, | |
perms=perms.PERM_CHANGE_PEOPLE, | |
klass=people.People) | |
or perms.is_idcard_editor(user)) | |
return allowed | |
def get_list_display(self, request): | |
""" | |
Hides the `display_image` field if user is not superuser or has no permissions to update the | |
:class:`directory.models.people.People` | |
:param request: Http request | |
:returns: List of displayed fields | |
""" | |
user = request.user | |
list_display = super(PeopleAdmin, self).get_list_display(request) | |
if user.is_superuser: | |
return list_display | |
user_have_somme_perms = get_objects_for_user(user, | |
perms=['directory.change_people'], | |
klass=people.People, | |
with_superuser=True) | |
if user_have_somme_perms: | |
return list_display | |
if 'display_image' in self.list_editable: | |
self.list_editable.remove('display_image') | |
return list_display | |
def get_list_display_links(self, request, list_display): | |
""" | |
Hides the link on `full_name` field if user is not superuser or has no permissions to update the | |
:class:`directory.models.P | |
:param request: Http request | |
:param list_display: list of displayed fields | |
:returns: list of displayed links | |
""" | |
display_links = super(PeopleAdmin, self).get_list_display_links(request, list_display) | |
user = request.user | |
settings.DEBUG and logger.debug('PeopleAdmin::get_list_display_links() user = %s', user) | |
if user.is_superuser: | |
return display_links | |
user_have_somme_perms = get_objects_for_user(user, | |
perms=['directory.change_people', 'directory.delete_people', ], | |
klass=people.People, | |
with_superuser=True) | |
if user_have_somme_perms: | |
return display_links | |
if 'full_name' in display_links: | |
display_links.remove('full_name') | |
return display_links | |
def get_actions(self, request): | |
""" | |
Removes action `action_create_idcards` for: | |
+ non-superuser | |
* users not having the permission `directory.create_idcard_people` | |
:param request: HTTP request | |
:returns: Allowed actions | |
""" | |
user = request.user | |
actions = super(PeopleAdmin, self).get_actions(request) | |
if user.is_superuser: | |
return actions | |
if not user.has_perm('directory.delete_people'): | |
del actions['delete_selected'] | |
return actions | |
def rendered_hierarchy(self, obj): | |
""" | |
Gets the direct hierarchy and the displayed one | |
:param obj: Current instance | |
:returns: formatted HTML chunk | |
""" | |
direct_hierarchy = obj.hierarchy | |
displayed_hierarchy = obj.hierarchy.get_displayed_hierarchy() | |
rendered = render_to_string('directory/snippets/hierarchy.html', {'hierarchy': direct_hierarchy, | |
'displayed_hierarchy': displayed_hierarchy}) | |
return mark_safe(rendered) | |
rendered_hierarchy.short_description = _('Hierarchy') | |
def full_name(self, obj): | |
""" | |
Gets the full name of the current :class:`directory.objects.People` instance | |
:param obj: Current instance | |
:returns: formatted HTML chunk | |
""" | |
return mark_safe(obj.full_name) | |
full_name.short_description = _('Full name') | |
def phone(self, obj): | |
""" | |
Gets the phone numbers of the current :class:`directory.objects.People` instance, using a template | |
:param obj: Current instance | |
:returns: formatted HTML chunk | |
""" | |
rendered = render_to_string('directory/snippets/phone.html', {'object': obj}) | |
return mark_safe(rendered) | |
phone.short_description = _('Phone') | |
def image_thumb(self, obj): | |
""" | |
Gets the photo thumbnail of the current :class:`directory.objects.People` instance | |
:param obj: Current instance | |
:returns: formatted HTML chunk | |
""" | |
context = {'object': obj} | |
logger.debug('PeopleAdmin::image_thumb(%s) obj.image__class__.__name__ = %s', | |
obj, obj.image.__class__.__name__) | |
rendered = render_to_string('directory/admin/snippets/people/image_thumb.html', context) | |
return mark_safe(rendered) | |
image_thumb.short_description = _('Photo') | |
def idcard(self, obj): | |
""" | |
Gets the id card data of the current :class:`directory.objects.People` instance | |
:param obj: Current instance | |
:returns: formatted HTML chunk | |
""" | |
return mark_safe(render_to_string('directory/admin/snippets/people/idcard.html', {'object': obj})) | |
idcard.short_description = _('Id Card') | |
# Actions | |
def action_mutate(self, request, queryset): | |
""" | |
Moves peoples and images from there onw hierarchy to the ``Mutation`` hierarchy, where they can be found to be | |
re-mutated from by another directory editor. | |
:param request: HTTP Request | |
:param queryset: Selected peoples | |
:returns: Nothing | |
""" | |
mutation_hierarchy = utilities.get_mutation_hierarchy(request) | |
mutation_image_folder = utilities.get_mutation_image_folder(request) | |
group = a_models.Group.objects.get(name=settings.DIRECTORY_EDITOR_GROUP_NAME) | |
users = group.user_set.all() | |
for _people in queryset: | |
# Moves the people to ``Mutation`` | |
utilities.move_people_to_mutation(_people, request, mutation_hierarchy) | |
# Moves the people image to ``Mutation`` | |
utilities.move_image_to_mutation(_people, request, mutation_image_folder) | |
# Deletes th id_card data | |
utilities.delete_idcard_data(_people, request) | |
# Change permissions on people | |
for user in users: | |
perms.add_perms_on_peoples(user, dry_run=False, wanted_peoples=queryset) | |
action_mutate.short_description = _('Mutate selected peoples') | |
def action_delete_idcards(self, request, queryset): | |
""" | |
Action to delete id card data for a given queryset | |
:param request: HTTP Request | |
:param queryset: Selected peoples | |
:returns: Nothing | |
""" | |
for _people in queryset: | |
utilities.delete_idcard_data(_people, request) | |
action_delete_idcards.short_description = _('Delete id cards') | |
def action_create_idcards(self, request, queryset): | |
""" | |
Action to draw some ID cards for a given queryset | |
:param request: HTTP Request | |
:param queryset: Selected peoples | |
:returns: HTTP Response with PDF inside | |
""" | |
error_peoples = [] | |
for _people in queryset: | |
if _people.image is None: | |
error_peoples.append(_people) | |
messages.warning(request, _('There is no photo for %(people)s, please add one.') % {'people': _people}) | |
people_list = [_people for _people in queryset if _people.image if not None] | |
generator = IdCardGenerator() | |
card_pdf = generator.generate_idcards(people_list=people_list) | |
response = HttpResponse(content=card_pdf, content_type='application/pdf') | |
disposition = 'attachment; filename="idcards.pdf"' | |
response['Content-Disposition'] = disposition | |
return response | |
action_create_idcards.short_description = _('Create professional identity cards') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment