Get rid of eval in metadata type default and lookup fields. gh-issue #151.
This commit is contained in:
@@ -71,6 +71,7 @@ What's new in Mayan EDMS v2.0
|
|||||||
* Document image and intermediate file caching now has it's own storage backend.
|
* Document image and intermediate file caching now has it's own storage backend.
|
||||||
* RGB tags
|
* RGB tags
|
||||||
* ``performupgrade`` management command.
|
* ``performupgrade`` management command.
|
||||||
|
* Removal of eval from metadata type defaults and lookup fields. Django's own template language is now used instead.
|
||||||
|
|
||||||
Upgrading from a previous version
|
Upgrading from a previous version
|
||||||
=================================
|
=================================
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
from .classes import MetadataLookup # NOQA
|
||||||
|
|||||||
@@ -104,7 +104,9 @@ def get_metadata_string(document):
|
|||||||
"""
|
"""
|
||||||
Return a formated representation of a document's metadata values
|
Return a formated representation of a document's metadata values
|
||||||
"""
|
"""
|
||||||
return ', '.join(['%s - %s' % (document_metadata.metadata_type, document_metadata.value) for document_metadata in document.metadata.all()])
|
return ', '.join(
|
||||||
|
['%s - %s' % (document_metadata.metadata_type, document_metadata.value) for document_metadata in document.metadata.all()]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def convert_dict_to_dict_list(dictionary):
|
def convert_dict_to_dict_list(dictionary):
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from .models import MetadataType
|
|
||||||
|
|
||||||
|
|
||||||
class DocumentMetadataHelper(object):
|
class DocumentMetadataHelper(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -17,7 +16,35 @@ class DocumentMetadataHelper(object):
|
|||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
try:
|
try:
|
||||||
return self.instance.metadata.get(metadata_type__name=name).value
|
return self.instance.metadata.get(metadata_type__name=name).value
|
||||||
except MetadataType.DoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
raise AttributeError(
|
raise AttributeError(
|
||||||
_('\'metadata\' object has no attribute \'%s\'') % name
|
_('\'metadata\' object has no attribute \'%s\'') % name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MetadataLookup(object):
|
||||||
|
_registry = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_as_context(cls):
|
||||||
|
result = {}
|
||||||
|
for entry in cls._registry:
|
||||||
|
result[entry.name] = entry.value
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_as_help_text(cls):
|
||||||
|
result = []
|
||||||
|
for entry in cls._registry:
|
||||||
|
result.append(
|
||||||
|
'{{{{ {0} }}}} = "{1}"'.format(entry.name, entry.description)
|
||||||
|
)
|
||||||
|
|
||||||
|
return ' '.join(result)
|
||||||
|
|
||||||
|
def __init__(self, description, name, value):
|
||||||
|
self.description = description
|
||||||
|
self.name = name
|
||||||
|
self.value = value
|
||||||
|
self.__class__._registry.append(self)
|
||||||
|
|||||||
@@ -1,16 +1,26 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import shlex
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.forms.formsets import formset_factory
|
from django.forms.formsets import formset_factory
|
||||||
from django.template import Context, Template
|
from django.template import Context, Template
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import string_concat, ugettext_lazy as _
|
||||||
|
|
||||||
|
from .classes import MetadataLookup
|
||||||
from .models import MetadataType
|
from .models import MetadataType
|
||||||
|
|
||||||
|
|
||||||
class MetadataForm(forms.Form):
|
class MetadataForm(forms.Form):
|
||||||
|
@staticmethod
|
||||||
|
def comma_splitter(string):
|
||||||
|
splitter = shlex.shlex(string.encode('utf-8'), posix=True)
|
||||||
|
splitter.whitespace = ','.encode('utf-8')
|
||||||
|
splitter.whitespace_split = True
|
||||||
|
splitter.commenters = ''.encode('utf-8')
|
||||||
|
return list(splitter)
|
||||||
|
|
||||||
def clean_value(self):
|
def clean_value(self):
|
||||||
metadata_type = MetadataType.objects.get(pk=self.cleaned_data['id'])
|
metadata_type = MetadataType.objects.get(pk=self.cleaned_data['id'])
|
||||||
@@ -66,23 +76,32 @@ class MetadataForm(forms.Form):
|
|||||||
self.fields['value'].required = False
|
self.fields['value'].required = False
|
||||||
|
|
||||||
self.fields['name'].initial = '%s%s' % (
|
self.fields['name'].initial = '%s%s' % (
|
||||||
(self.metadata_type.label if self.metadata_type.label else self.metadata_type.name),
|
(
|
||||||
|
self.metadata_type.label if self.metadata_type.label else self.metadata_type.name
|
||||||
|
),
|
||||||
required_string
|
required_string
|
||||||
)
|
)
|
||||||
self.fields['id'].initial = self.metadata_type.pk
|
self.fields['id'].initial = self.metadata_type.pk
|
||||||
|
|
||||||
if self.metadata_type.lookup:
|
if self.metadata_type.lookup:
|
||||||
try:
|
try:
|
||||||
#choices = eval(self.metadata_type.lookup, setting_available_models.value) #####
|
template = Template(self.metadata_type.lookup)
|
||||||
choices = []
|
context = Context(MetadataLookup.get_as_context())
|
||||||
self.fields['value'] = forms.ChoiceField(label=self.fields['value'].label)
|
choices = MetadataForm.comma_splitter(
|
||||||
|
template.render(context=context)
|
||||||
|
)
|
||||||
|
self.fields['value'] = forms.ChoiceField(
|
||||||
|
label=self.fields['value'].label
|
||||||
|
)
|
||||||
choices = zip(choices, choices)
|
choices = zip(choices, choices)
|
||||||
if not required:
|
if not required:
|
||||||
choices.insert(0, ('', '------'))
|
choices.insert(0, ('', '------'))
|
||||||
self.fields['value'].choices = choices
|
self.fields['value'].choices = choices
|
||||||
self.fields['value'].required = required
|
self.fields['value'].required = required
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.fields['value'].initial = exception
|
self.fields['value'].initial = _(
|
||||||
|
'Lookup value error: %s'
|
||||||
|
) % exception
|
||||||
self.fields['value'].widget = forms.TextInput(
|
self.fields['value'].widget = forms.TextInput(
|
||||||
attrs={'readonly': 'readonly'}
|
attrs={'readonly': 'readonly'}
|
||||||
)
|
)
|
||||||
@@ -95,8 +114,12 @@ class MetadataForm(forms.Form):
|
|||||||
self.fields['value'].initial = result
|
self.fields['value'].initial = result
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
self.fields['value'].initial = _(
|
self.fields['value'].initial = _(
|
||||||
'Error: %s'
|
'Default value error: %s'
|
||||||
) % exception
|
) % exception
|
||||||
|
self.fields['value'].widget = forms.TextInput(
|
||||||
|
attrs={'readonly': 'readonly'}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
id = forms.CharField(label=_('ID'), widget=forms.HiddenInput)
|
id = forms.CharField(label=_('ID'), widget=forms.HiddenInput)
|
||||||
|
|
||||||
@@ -123,6 +146,20 @@ class AddMetadataForm(forms.Form):
|
|||||||
self.fields['metadata_type'].queryset = document_type.metadata.all()
|
self.fields['metadata_type'].queryset = document_type.metadata.all()
|
||||||
|
|
||||||
|
|
||||||
|
class MetadataTypeForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
fields = ('name', 'label', 'default', 'lookup', 'validation')
|
||||||
|
model = MetadataType
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(MetadataTypeForm, self).__init__(*args, **kwargs)
|
||||||
|
self.fields['lookup'].help_text = string_concat(
|
||||||
|
self.fields['lookup'].help_text,
|
||||||
|
_(' Available template context variables: '),
|
||||||
|
MetadataLookup.get_as_help_text()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MetadataRemoveForm(MetadataForm):
|
class MetadataRemoveForm(MetadataForm):
|
||||||
update = forms.BooleanField(
|
update = forms.BooleanField(
|
||||||
initial=False, label=_('Remove'), required=False
|
initial=False, label=_('Remove'), required=False
|
||||||
|
|||||||
@@ -14,7 +14,24 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='metadatatype',
|
model_name='metadatatype',
|
||||||
name='validation',
|
name='validation',
|
||||||
field=models.CharField(blank=True, max_length=64, verbose_name='Validation function name', choices=[(b'metadata.validators.DateAndTimeValidator', b'metadata.validators.DateAndTimeValidator'), (b'metadata.validators.DateValidator', b'metadata.validators.DateValidator'), (b'metadata.validators.TimeValidator', b'metadata.validators.TimeValidator')]),
|
field=models.CharField(
|
||||||
|
blank=True, max_length=64,
|
||||||
|
verbose_name='Validation function name',
|
||||||
|
choices=[
|
||||||
|
(
|
||||||
|
b'metadata.validators.DateAndTimeValidator',
|
||||||
|
b'metadata.validators.DateAndTimeValidator'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
b'metadata.validators.DateValidator',
|
||||||
|
b'metadata.validators.DateValidator'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
b'metadata.validators.TimeValidator',
|
||||||
|
b'metadata.validators.TimeValidator'
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
preserve_default=True,
|
preserve_default=True,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -25,28 +25,36 @@ class MetadataType(models.Model):
|
|||||||
"""
|
"""
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
max_length=48,
|
max_length=48,
|
||||||
help_text=_('Name used by other apps to reference this value. Do not use python reserved words, or spaces.'),
|
help_text=_(
|
||||||
|
'Name used by other apps to reference this value. '
|
||||||
|
'Do not use python reserved words, or spaces.'
|
||||||
|
),
|
||||||
unique=True, verbose_name=_('Name')
|
unique=True, verbose_name=_('Name')
|
||||||
)
|
)
|
||||||
label = models.CharField(max_length=48, verbose_name=_('Label'))
|
label = models.CharField(max_length=48, verbose_name=_('Label'))
|
||||||
default = models.CharField(
|
default = models.CharField(
|
||||||
blank=True, max_length=128, null=True,
|
blank=True, max_length=128, null=True,
|
||||||
help_text=_('Enter a template to render. Use Django\'s default templating language (https://docs.djangoproject.com/en/1.7/ref/templates/builtins/)'),
|
help_text=_(
|
||||||
|
'Enter a template to render. '
|
||||||
|
'Use Django\'s default templating language '
|
||||||
|
'(https://docs.djangoproject.com/en/1.7/ref/templates/builtins/)'
|
||||||
|
),
|
||||||
verbose_name=_('Default')
|
verbose_name=_('Default')
|
||||||
)
|
)
|
||||||
# TODO: Add enable_lookup boolean to allow users to switch the lookup on and
|
|
||||||
# off without losing the lookup expression
|
|
||||||
lookup = models.TextField(
|
lookup = models.TextField(
|
||||||
blank=True, null=True,
|
blank=True, null=True,
|
||||||
help_text=_('Enter a string to be evaluated that returns an iterable.'),
|
help_text=_(
|
||||||
|
'Enter a template to render. '
|
||||||
|
'Must result in a command delimited string. '
|
||||||
|
'Use Django\'s default templating language '
|
||||||
|
'(https://docs.djangoproject.com/en/1.7/ref/templates/builtins/).'
|
||||||
|
),
|
||||||
verbose_name=_('Lookup')
|
verbose_name=_('Lookup')
|
||||||
)
|
)
|
||||||
validation = models.CharField(
|
validation = models.CharField(
|
||||||
blank=True, choices=validation_choices(), max_length=64,
|
blank=True, choices=validation_choices(), max_length=64,
|
||||||
verbose_name=_('Validation function name')
|
verbose_name=_('Validation function name')
|
||||||
)
|
)
|
||||||
# TODO: Find a different way to let users know what models and functions are
|
|
||||||
# available now that we removed these from the help_text
|
|
||||||
objects = MetadataTypeManager()
|
objects = MetadataTypeManager()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ from documents.views import DocumentListView
|
|||||||
from permissions import Permission
|
from permissions import Permission
|
||||||
|
|
||||||
from .api import save_metadata_list
|
from .api import save_metadata_list
|
||||||
from .forms import AddMetadataForm, MetadataFormSet, MetadataRemoveFormSet
|
from .forms import (
|
||||||
|
AddMetadataForm, MetadataFormSet, MetadataRemoveFormSet, MetadataTypeForm
|
||||||
|
)
|
||||||
from .models import DocumentMetadata, MetadataType
|
from .models import DocumentMetadata, MetadataType
|
||||||
from .permissions import (
|
from .permissions import (
|
||||||
permission_metadata_document_add, permission_metadata_document_edit,
|
permission_metadata_document_add, permission_metadata_document_edit,
|
||||||
@@ -148,7 +150,8 @@ def metadata_edit(request, document_id=None, document_id_list=None):
|
|||||||
else:
|
else:
|
||||||
messages.error(
|
messages.error(
|
||||||
request, _(
|
request, _(
|
||||||
'Error editing metadata for document %(document)s; %(exception)s.'
|
'Error editing metadata for document: '
|
||||||
|
'%(document)s; %(exception)s.'
|
||||||
) % {
|
) % {
|
||||||
'document': document,
|
'document': document,
|
||||||
'exception': ', '.join(exception.messages)
|
'exception': ', '.join(exception.messages)
|
||||||
@@ -157,7 +160,9 @@ def metadata_edit(request, document_id=None, document_id_list=None):
|
|||||||
else:
|
else:
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
_('Metadata for document %s edited successfully.') % document
|
_(
|
||||||
|
'Metadata for document %s edited successfully.'
|
||||||
|
) % document
|
||||||
)
|
)
|
||||||
|
|
||||||
return HttpResponseRedirect(next)
|
return HttpResponseRedirect(next)
|
||||||
@@ -192,7 +197,10 @@ def metadata_add(request, document_id=None, document_id_list=None):
|
|||||||
documents = [get_object_or_404(Document, pk=document_id)]
|
documents = [get_object_or_404(Document, pk=document_id)]
|
||||||
elif document_id_list:
|
elif document_id_list:
|
||||||
documents = [
|
documents = [
|
||||||
get_object_or_404(Document.objects.select_related('document_type'), pk=document_id) for document_id in document_id_list.split(',')
|
get_object_or_404(
|
||||||
|
Document.objects.select_related('document_type'),
|
||||||
|
pk=document_id
|
||||||
|
) for document_id in document_id_list.split(',')
|
||||||
]
|
]
|
||||||
if len(set([document.document_type.pk for document in documents])) > 1:
|
if len(set([document.document_type.pk for document in documents])) > 1:
|
||||||
messages.error(
|
messages.error(
|
||||||
@@ -253,11 +261,15 @@ def metadata_add(request, document_id=None, document_id_list=None):
|
|||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
_(
|
_(
|
||||||
'Error adding metadata type "%(metadata_type)s" to document: %(document)s; %(exception)s'
|
'Error adding metadata type '
|
||||||
|
'"%(metadata_type)s" to document: '
|
||||||
|
'%(document)s; %(exception)s'
|
||||||
) % {
|
) % {
|
||||||
'metadata_type': metadata_type,
|
'metadata_type': metadata_type,
|
||||||
'document': document,
|
'document': document,
|
||||||
'exception': ', '.join(getattr(exception, 'messages', exception))
|
'exception': ', '.join(
|
||||||
|
getattr(exception, 'messages', exception)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -265,17 +277,21 @@ def metadata_add(request, document_id=None, document_id_list=None):
|
|||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
_(
|
_(
|
||||||
'Metadata type: %(metadata_type)s successfully added to document %(document)s.'
|
'Metadata type: %(metadata_type)s '
|
||||||
|
'successfully added to document %(document)s.'
|
||||||
) % {
|
) % {
|
||||||
'metadata_type': metadata_type, 'document': document
|
'metadata_type': metadata_type,
|
||||||
|
'document': document
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
messages.warning(
|
messages.warning(
|
||||||
request, _(
|
request, _(
|
||||||
'Metadata type: %(metadata_type)s already present in document %(document)s.'
|
'Metadata type: %(metadata_type)s already '
|
||||||
|
'present in document %(document)s.'
|
||||||
) % {
|
) % {
|
||||||
'metadata_type': metadata_type, 'document': document
|
'metadata_type': metadata_type,
|
||||||
|
'document': document
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -368,7 +384,11 @@ def metadata_remove(request, document_id=None, document_id_list=None):
|
|||||||
|
|
||||||
post_action_redirect = reverse('documents:document_list_recent')
|
post_action_redirect = reverse('documents:document_list_recent')
|
||||||
|
|
||||||
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', post_action_redirect)))
|
next = request.POST.get(
|
||||||
|
'next', request.GET.get(
|
||||||
|
'next', request.META.get('HTTP_REFERER', post_action_redirect)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
metadata = {}
|
metadata = {}
|
||||||
for document in documents:
|
for document in documents:
|
||||||
@@ -397,15 +417,34 @@ def metadata_remove(request, document_id=None, document_id_list=None):
|
|||||||
|
|
||||||
for form in formset.forms:
|
for form in formset.forms:
|
||||||
if form.cleaned_data['update']:
|
if form.cleaned_data['update']:
|
||||||
metadata_type = get_object_or_404(MetadataType, pk=form.cleaned_data['id'])
|
metadata_type = get_object_or_404(
|
||||||
|
MetadataType, pk=form.cleaned_data['id']
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
document_metadata = DocumentMetadata.objects.get(document=document, metadata_type=metadata_type)
|
document_metadata = DocumentMetadata.objects.get(
|
||||||
|
document=document, metadata_type=metadata_type
|
||||||
|
)
|
||||||
document_metadata.delete()
|
document_metadata.delete()
|
||||||
messages.success(request, _('Successfully remove metadata type "%(metadata_type)s" from document: %(document)s.') % {
|
messages.success(
|
||||||
'metadata_type': metadata_type, 'document': document})
|
request,
|
||||||
|
_(
|
||||||
|
'Successfully remove metadata type "%(metadata_type)s" from document: %(document)s.'
|
||||||
|
) % {
|
||||||
|
'metadata_type': metadata_type,
|
||||||
|
'document': document
|
||||||
|
}
|
||||||
|
)
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
messages.error(request, _('Error removing metadata type "%(metadata_type)s" from document: %(document)s; %(exception)s') % {
|
messages.error(
|
||||||
'metadata_type': metadata_type, 'document': document, 'exception': ', '.join(exception.messages)})
|
request,
|
||||||
|
_(
|
||||||
|
'Error removing metadata type "%(metadata_type)s" from document: %(document)s; %(exception)s'
|
||||||
|
) % {
|
||||||
|
'metadata_type': metadata_type,
|
||||||
|
'document': document,
|
||||||
|
'exception': ', '.join(exception.messages)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return HttpResponseRedirect(next)
|
return HttpResponseRedirect(next)
|
||||||
|
|
||||||
@@ -429,23 +468,32 @@ def metadata_remove(request, document_id=None, document_id_list=None):
|
|||||||
|
|
||||||
|
|
||||||
def metadata_multiple_remove(request):
|
def metadata_multiple_remove(request):
|
||||||
return metadata_remove(request, document_id_list=request.GET.get('id_list', []))
|
return metadata_remove(
|
||||||
|
request, document_id_list=request.GET.get('id_list', [])
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def metadata_view(request, document_id):
|
def metadata_view(request, document_id):
|
||||||
document = get_object_or_404(Document, pk=document_id)
|
document = get_object_or_404(Document, pk=document_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
Permission.check_permissions(request.user, [permission_metadata_document_view])
|
Permission.check_permissions(
|
||||||
|
request.user, [permission_metadata_document_view]
|
||||||
|
)
|
||||||
except PermissionDenied:
|
except PermissionDenied:
|
||||||
AccessControlList.objects.check_access(permission_metadata_document_view, request.user, document)
|
AccessControlList.objects.check_access(
|
||||||
|
permission_metadata_document_view, request.user, document
|
||||||
|
)
|
||||||
|
|
||||||
return render_to_response('appearance/generic_list.html', {
|
return render_to_response('appearance/generic_list.html', {
|
||||||
'title': _('Metadata for document: %s') % document,
|
'title': _('Metadata for document: %s') % document,
|
||||||
'object_list': document.metadata.all(),
|
'object_list': document.metadata.all(),
|
||||||
'extra_columns': [
|
'extra_columns': [
|
||||||
{'name': _('Value'), 'attribute': 'value'},
|
{'name': _('Value'), 'attribute': 'value'},
|
||||||
{'name': _('Required'), 'attribute': encapsulate(lambda x: x.metadata_type in document.document_type.metadata.filter(required=True))}
|
{
|
||||||
|
'name': _('Required'),
|
||||||
|
'attribute': encapsulate(lambda x: x.metadata_type in document.document_type.metadata.filter(required=True))
|
||||||
|
}
|
||||||
],
|
],
|
||||||
'hide_link': True,
|
'hide_link': True,
|
||||||
'object': document,
|
'object': document,
|
||||||
@@ -455,6 +503,7 @@ def metadata_view(request, document_id):
|
|||||||
# Setup views
|
# Setup views
|
||||||
class MetadataTypeCreateView(SingleObjectCreateView):
|
class MetadataTypeCreateView(SingleObjectCreateView):
|
||||||
extra_context = {'title': _('Create metadata type')}
|
extra_context = {'title': _('Create metadata type')}
|
||||||
|
form_class = MetadataTypeForm
|
||||||
model = MetadataType
|
model = MetadataType
|
||||||
post_action_redirect = reverse_lazy('metadata:setup_metadata_type_list')
|
post_action_redirect = reverse_lazy('metadata:setup_metadata_type_list')
|
||||||
view_permission = permission_metadata_type_create
|
view_permission = permission_metadata_type_create
|
||||||
@@ -474,6 +523,7 @@ class MetadataTypeDeleteView(SingleObjectDeleteView):
|
|||||||
|
|
||||||
|
|
||||||
class MetadataTypeEditView(SingleObjectEditView):
|
class MetadataTypeEditView(SingleObjectEditView):
|
||||||
|
form_class = MetadataTypeForm
|
||||||
model = MetadataType
|
model = MetadataType
|
||||||
post_action_redirect = reverse_lazy('metadata:setup_metadata_type_list')
|
post_action_redirect = reverse_lazy('metadata:setup_metadata_type_list')
|
||||||
view_permission = permission_metadata_type_edit
|
view_permission = permission_metadata_type_edit
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import User, Group
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
@@ -7,6 +8,7 @@ from actstream import registry
|
|||||||
|
|
||||||
from common import menu_multi_item, menu_object, menu_secondary, menu_setup
|
from common import menu_multi_item, menu_object, menu_secondary, menu_setup
|
||||||
from common.apps import MayanAppConfig
|
from common.apps import MayanAppConfig
|
||||||
|
from metadata import MetadataLookup
|
||||||
from rest_api.classes import APIEndPoint
|
from rest_api.classes import APIEndPoint
|
||||||
|
|
||||||
from .links import (
|
from .links import (
|
||||||
@@ -28,6 +30,9 @@ class UserManagementApp(MayanAppConfig):
|
|||||||
|
|
||||||
APIEndPoint('users', app_name='user_management')
|
APIEndPoint('users', app_name='user_management')
|
||||||
|
|
||||||
|
MetadataLookup(description=_('All the groups.'), name='group', value=Group.objects.all())
|
||||||
|
MetadataLookup(description=_('All the users.'), name='users', value=get_user_model().objects.all())
|
||||||
|
|
||||||
menu_multi_item.bind_links(
|
menu_multi_item.bind_links(
|
||||||
links=[link_group_multiple_delete],
|
links=[link_group_multiple_delete],
|
||||||
sources=['user_management:group_list']
|
sources=['user_management:group_list']
|
||||||
|
|||||||
Reference in New Issue
Block a user