From 58e38c1ff90fff59952cc42c001eff07ae8cca72 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 9 Jan 2019 12:23:39 -0400 Subject: [PATCH 1/3] Improve FilteredSelectionForm Improve the configuration process of the FilteredSelectionForm form by adding Meta child class support. The child Meta class is defined in FilteredSelectionFormOptions. Signed-off-by: Roberto Rosario --- mayan/apps/common/forms.py | 104 ++++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/mayan/apps/common/forms.py b/mayan/apps/common/forms.py index 2b09759742..4a331e01ab 100644 --- a/mayan/apps/common/forms.py +++ b/mayan/apps/common/forms.py @@ -4,10 +4,13 @@ import os from django import forms from django.conf import settings +from django.core.exceptions import ImproperlyConfigured from django.db import models from django.utils.module_loading import import_string from django.utils.translation import ugettext_lazy as _ +from mayan.apps.acls.models import AccessControlList + from .classes import Package from .models import UserLocaleProfile from .utils import resolve_attribute @@ -111,7 +114,10 @@ class FileDisplayForm(forms.Form): text = forms.CharField( label='', widget=TextAreaDiv( - attrs={'class': 'full-height scrollable', 'data-height-difference': 270} + attrs={ + 'class': 'full-height scrollable', + 'data-height-difference': 270 + } ) ) @@ -125,6 +131,102 @@ class FileDisplayForm(forms.Form): self.fields['text'].initial = file_object.read() +class FilteredSelectionFormOptions(object): + # Dictionary list of option names and default values + option_definitions = ( + {'allow_multiple': False}, + {'field_name': None}, + {'help_text': None}, + {'label': None}, + {'model': None}, + {'permission': None}, + {'queryset': None}, + {'user': None}, + {'widget_class': None}, + {'widget_attributes': {'size': '10'}}, + ) + + def __init__(self, form, kwargs, options=None): + """ + Option definitions will be iterated. The option value will be + determined in the following order: as passed via keyword + arguments during form intialization, as form get_... method or + finally as static Meta options. This is to allow a form with + Meta options or method to be overrided at initialization + and increase the usability of a single class. + """ + for option_definition in self.option_definitions: + name = option_definition.keys()[0] + default_value = option_definition.values()[0] + + try: + # Check for a runtime value via kwargs + value = kwargs.pop(name) + except KeyError: + try: + # Check if there is a get_... method + value = getattr(self, 'get_{}'.format(name))() + except AttributeError: + try: + # Check the meta class options + value = getattr(options, name) + except AttributeError: + value = default_value + + setattr(self, name, value) + + +class FilteredSelectionForm(forms.Form): + """ + Form to select the from a list of choice filtered by access. Can be + configure to allow single or multiple selection. + """ + def __init__(self, *args, **kwargs): + opts = FilteredSelectionFormOptions( + form=self, kwargs=kwargs, options=getattr(self, 'Meta', None) + ) + + if opts.queryset is None: + if not opts.model: + raise ImproperlyConfigured( + '{} requires a queryset or a model to be specified as ' + 'a meta option or passed during initialization.'.format( + self.__class__ + ) + ) + + queryset = opts.model.objects.all() + else: + queryset = opts.queryset + + if not opts.widget_class: + if opts.allow_multiple: + extra_kwargs = {} + field_class = forms.ModelMultipleChoiceField + widget_class = forms.widgets.SelectMultiple + else: + extra_kwargs = {'empty_label': None} + field_class = forms.ModelChoiceField + widget_class = forms.widgets.Select + else: + widget_class = opts.widget_class + + super(FilteredSelectionForm, self).__init__(*args, **kwargs) + + if opts.permission: + queryset = AccessControlList.objects.filter_by_access( + permission=opts.permission, queryset=queryset, + user=opts.user + ) + + self.fields[opts.field_name] = field_class( + help_text=opts.help_text, label=opts.label, + queryset=queryset, required=True, + widget=widget_class(attrs=opts.widget_attributes), + **extra_kwargs + ) + + class LicenseForm(FileDisplayForm): DIRECTORY = () FILENAME = 'LICENSE' From 8f24b2ed801da5291bb79ba9b9b4b7e43b5224cf Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 9 Jan 2019 12:38:38 -0400 Subject: [PATCH 2/3] Improve Template hash calculation Calculate the Template hash from the content actually returned. Remove the newlines as these are irrelevant for HTML. Signed-off-by: Roberto Rosario --- mayan/apps/common/classes.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mayan/apps/common/classes.py b/mayan/apps/common/classes.py index ffd4b9e626..6af4eea5b4 100644 --- a/mayan/apps/common/classes.py +++ b/mayan/apps/common/classes.py @@ -301,7 +301,9 @@ class Template(object): self.__class__._registry[name] = self def get_absolute_url(self): - return reverse('rest_api:template-detail', args=(self.name,)) + return reverse( + viewname='rest_api:template-detail', kwargs={'template_pk': self.name} + ) def render(self, request): context = { @@ -313,8 +315,10 @@ class Template(object): context=context, ).render() - self.html = result.rendered_content - self.hex_hash = hashlib.sha256(result.content).hexdigest() + content = result.rendered_content.replace('\n', '') + + self.html = content + self.hex_hash = hashlib.sha256(content).hexdigest() return self From da1d32f6cdd174b60b7719f7d6066a3276e80d6e Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Wed, 9 Jan 2019 13:09:39 -0400 Subject: [PATCH 3/3] Rename common app migration Rename migration 0011_auto_20181229_0738 to 0012_auto_20181229_0738 to avoid conflict with an existing 0011_* migration. Signed-off-by: Roberto Rosario --- .../{0011_auto_20181229_0738.py => 0012_auto_20181229_0738.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename mayan/apps/common/migrations/{0011_auto_20181229_0738.py => 0012_auto_20181229_0738.py} (100%) diff --git a/mayan/apps/common/migrations/0011_auto_20181229_0738.py b/mayan/apps/common/migrations/0012_auto_20181229_0738.py similarity index 100% rename from mayan/apps/common/migrations/0011_auto_20181229_0738.py rename to mayan/apps/common/migrations/0012_auto_20181229_0738.py