def action(request, app, cls, action_name, pk=None): try: _model = apps.get_model(app, cls) except LookupError as e: return page_not_found(request, e, 'error404.html') for group in loader.actions[_model]: if action_name in loader.actions[_model][group]: break form_action = loader.actions[_model][group][action_name] action_title = form_action['title'] action_can_execute = form_action['can_execute'] action_condition = form_action['condition'] action_function = form_action['function'] action_message = 'message' in form_action and form_action['message'] or None action_permission = '{}.{}'.format(_model._meta.app_label, action_function.__name__) action_input = form_action['input'] redirect_to = form_action['redirect_to'] obj = pk and _model.objects.all(request.user).get(pk=pk) or _model() obj.request = request obj._user = request.user title = action_title if check_condition(action_condition, obj) and (not action_can_execute or permissions.check_group_or_permission( request, action_permission)): func = getattr(_model, action_function.__name__, action_function) form = factory.get_action_form(request, obj, form_action) if func.__code__.co_argcount > 1 or action_input: if form.is_valid(): if 'instance' in form.fields: obj = form.cleaned_data['instance'] func = getattr(obj, action_function.__name__, action_function) params = [] for param in func.__code__.co_varnames[1:func.__code__. co_argcount]: if param in form.cleaned_data: params.append(form.cleaned_data[param]) try: f_return = func(*params) if not redirect_to: if func.__code__.co_argcount > 1: return httprr(request, '..', action_message) else: return httprr(request, '.', action_message) else: return httprr( request, Template(redirect_to).render(Context({'self': obj})), action_message) except ValidationError as e: form.add_error(None, str(e.message)) else: try: if form.fields and form.is_valid() or not form.fields: if form.fields: obj = form.cleaned_data['instance'] func = getattr(obj, action_function.__name__, action_function) f_return = func() if not redirect_to: if func.__code__.co_argcount > 1: return httprr(request, '..', action_message) else: return httprr(request, '.', action_message) else: return httprr( request, Template(redirect_to).render(Context({'self': obj})), action_message) except ValidationError as e: return httprr(request, '.', str(e.message)) if form.title == DEFAULT_FORM_TITLE: form.title = action_title if form.submit_label == DEFAULT_SUBMIT_LABEL: form.submit_label = action_title return render(request, 'default.html', locals()) else: return HttpResponseForbidden()
def add_actions(self, obj, fieldset=None, subset_name=None, category=None, action_names=None): from djangoplus.cache import CACHE obj.request = self.request if not self.actions_cache: self.actions_cache = self.actions if not action_names: action_names = [] self.hash = abs(datetime.now().__hash__()) self.actions = copy.deepcopy(self.actions_cache) self.obj = obj for action_category in CACHE['INSTANCE_ACTIONS'][self.model]: for view_name in CACHE['INSTANCE_ACTIONS'][ self.model][action_category]: action = CACHE['INSTANCE_ACTIONS'][ self.model][action_category][view_name] action_function = action.get('function') action_verbose_name = action['verbose_name'] action_can_execute = get_can_execute(action) action_condition = action['condition'] action_style = action['style'] action_input = action['input'] action_inline = action['inline'] action_subsets = action['subsets'] action_icon = action['icon'] action_display = action['display'] action_expose = action['expose'] action_name = action_function.__name__ is_action_view = not hasattr(self.model, action_name) if action_name and action_style == 'popup' and not is_action_view: func = getattr(self.model, action_name) if not (count_parameters_names(func) > 1 or action_input or action_display): action_style = 'ajax' # it is a dropdown in a model panel if fieldset is not None: if fieldset: if action_name not in CACHE['FIELDSET_ACTIONS'][ self.model][fieldset]: continue else: # if the action was included in any fieldset, # it can not be displayed in page's action panel add_action = True for title, action_names in list( CACHE['FIELDSET_ACTIONS'][self.model].items()): if action_name in action_names: add_action = False break if not add_action: continue else: # it is a dropdown in a paginator if action_names: # it is a relation paginator if view_name not in action_names: continue else: # it is a list view paginator should_add_this_action = should_add_action( action_inline, action_subsets, subset_name) add_action = view_name in action_names or should_add_this_action if not add_action: continue lookups = self.request.user.get_permission_mapping( self.model, obj).get(action_name) if lookups: forbidden = True for key, value in lookups: if self.model.objects.filter(pk=obj.pk, **{ '{}__in'.format(key): value }).exists(): forbidden = False break if forbidden: continue if True not in action_expose and 'web' not in action_expose: continue if not permissions.check_group_or_permission( self.request, action_can_execute): continue if not check_condition(self.request.user, action_condition, obj): continue if is_action_view: action_url = '/{}/{}/'.format( get_metadata(self.model, 'app_label'), action_name) else: action_url = '/action/{}/{}/{}/'.format( get_metadata(self.model, 'app_label'), self.model.__name__.lower(), view_name) action_category = category or action_category self.add_action(action_verbose_name, action_url, action_style, action_icon, action_category)
def add_actions(self, obj, inline=False, fieldset_title=None, subset_name=None, category=None): from djangoplus.cache import loader obj.request = self.request if not self.actions_cache: self.actions_cache = self.actions self.hash = abs(datetime.now().__hash__()) self.actions = copy.deepcopy(self.actions_cache) self.obj = obj if inline: if self.model in loader.add_inline_actions: for add_inline_action in loader.add_inline_actions[self.model]: if add_inline_action['subset'] is True or add_inline_action[ 'subset'] == subset_name: if permissions.check_group_or_permission( self.request, add_inline_action['can_execute']): self.add_action(add_inline_action['title'], add_inline_action['url'], 'popup', 'fa fa-plus') for action_category in loader.actions[self.model]: for view_name in loader.actions[self.model][action_category]: action = loader.actions[self.model][action_category][view_name] action_function = action.get('function') action_title = action['title'] action_can_execute = action['can_execute'] action_condition = action['condition'] action_css = action['css'] action_input = action['input'] action_inline = action['inline'] action_icon = action['icon'] action_name = action_function.__name__ is_action_view = not hasattr(self.model, action_name) if action_name and action_css == 'popup' and not is_action_view: func = getattr(self.model, action_name) action_css = (func.__code__.co_argcount > 1 or action_input) and action_css or 'ajax' # it is a dropdown in a model panel if fieldset_title is not None: if fieldset_title: if action_name not in loader.fieldset_actions[ self.model][fieldset_title]: continue else: # if the action was included in any fieldset it can not be displayed in page's action panel add_action = True for fieldset_title2, action_names in list( loader.fieldset_actions[self.model].items()): if action_name in action_names: add_action = False break if not add_action: continue else: # it is a dropdown in a paginator if action_inline is not True and ( subset_name not in loader.subset_actions[self.model] or action_name not in loader.subset_actions[ self.model][subset_name]): continue if not permissions.check_group_or_permission( self.request, action_can_execute): continue if not check_condition(action_condition, obj): continue if is_action_view: action_url = '/{}/{}/'.format( get_metadata(self.model, 'app_label'), action_name) else: action_url = '/action/{}/{}/{}/'.format( get_metadata(self.model, 'app_label'), self.model.__name__.lower(), view_name) self.add_action(action_title, action_url, action_css, action_icon, category or action_category)
def action(request, app, cls, action_name, pk=None): try: _model = apps.get_model(app, cls) except LookupError as e: return page_not_found(request, e, 'error404.html') for group in loader.instance_actions[_model]: if action_name in loader.instance_actions[_model][group]: break form_action = loader.instance_actions[_model][group][action_name] action_verbose_name = form_action['verbose_name'] action_can_execute = form_action['can_execute'] action_condition = form_action['condition'] action_function = form_action['function'] action_message = 'message' in form_action and form_action['message'] or None action_permission = '{}.{}'.format(_model._meta.app_label, action_function.__name__) action_input = form_action['input'] action_display = form_action['display'] action_style = form_action['style'] action_redirect = form_action['redirect_to'] obj = pk and _model.objects.all( request.user).distinct().get(pk=pk) or _model() obj.request = request obj._user = request.user title = action_verbose_name redirect_to = None if check_condition(request.user, action_condition, obj) and (not action_can_execute or permissions.check_group_or_permission( request, action_permission)): f_return = None func = getattr(_model, action_function.__name__, action_function) form = factory.get_action_form(request, obj, form_action) if count_parameters_names(func) > 1 or action_input: if form.is_valid(): if 'instance' in form.fields: obj = form.cleaned_data['instance'] func = getattr(obj, action_function.__name__, action_function) params = [] for param in get_parameters_names(func, include_annotated=True): if param in form.cleaned_data: params.append(form.cleaned_data[param]) else: params.append( get_role_value_for_action(func, request.user, param)) try: f_return = func(*params) if not action_redirect: if count_parameters_names(func) > 0 or action_display: redirect_to = '..' else: redirect_to = '.' else: redirect_to = Template(action_redirect).render( Context({'self': obj})) except ValidationError as e: form.add_error(None, str(e.message)) else: try: if form.fields and form.is_valid() or not form.fields: if 'instance' in form.fields: obj = form.cleaned_data['instance'] func = getattr(obj, action_function.__name__, action_function) params = [] for param in get_parameters_names(func, include_annotated=True): params.append( get_role_value_for_action(func, request.user, param)) f_return = func(*params) if not action_redirect: if count_parameters_names(func) > 0 or action_display: redirect_to = '..' else: redirect_to = '.' else: redirect_to = Template(action_redirect).render( Context({'self': obj})) except ValidationError as e: if form.fields: form.add_error(None, str(e.message)) return httprr(request, '.', e.message, error=True) if f_return: template_name = '{}.html'.format(action_function.__name__) return return_response(f_return, request, title, action_style, template_name) elif redirect_to: return httprr(request, redirect_to, action_message) if form.title == _('Form'): form.title = action_verbose_name if form.submit_label == _('Send'): form.submit_label = action_verbose_name return render(request, 'default.html', locals()) else: return HttpResponseForbidden()
def __init__(self, request, obj, current_tab=None, parent=None, fieldsets=None, complete=True, readonly=False, printable=True): super(ModelPanel, self).__init__(obj.pk, request) self.obj = obj self.title = obj.pk and str(obj) or get_metadata( type(obj), 'verbose_name') self.id = self.title self.tabs = [] self.current_tab = current_tab self.message = None self.complete = complete self.readonly = readonly self.printable = printable self.drop_down = None fieldsets = fieldsets or get_metadata(type(obj), 'view_fieldsets', []) if not fieldsets: fieldsets = get_fieldsets(type(obj)) if self.complete: self.drop_down = ModelDropDown(self.request, type(self.obj)) self.drop_down.add_actions(self.obj, fieldset='') if self.printable: print_url = '?pdf={}&pk='.format(self.id) self.drop_down.add_action('Imprimir', url=print_url, css='ajax', icon='fa-print', category='Imprimir') else: self.drop_down = GroupDropDown(self.request) self.fieldsets_with_tab_name = [] self.fieldsets_without_tab_name = [] model = type(self.obj) obj.as_pdf = self.as_pdf for fieldset in fieldsets: title, info = fieldset tab_name = None drop_down = ModelDropDown(self.request, model) fieldset_actions = info.get('actions', []) fieldset_image = info.get('image') if fieldset_actions: drop_down.add_actions(self.obj, fieldset=title) if 'condition' in fieldset[1]: condition = fieldset[1]['condition'] self.obj.request = self.request if not check_condition(self.request.user, condition, self.obj): continue if '::' in title: tab_name, title = title.split('::') url = '/view/{}/{}/{}/{}/'.format( get_metadata(model, 'app_label'), model.__name__.lower(), self.obj.pk, slugify(tab_name)) tab = (tab_name, url) if not self.tabs and not self.current_tab: self.current_tab = slugify(tab_name) if tab not in self.tabs: self.tabs.append(tab) if not tab_name or slugify( tab_name) == self.current_tab or self.as_pdf: fieldset_dict = dict(title=title or 'Dados Gerais', tab_name=tab_name, fields=[], paginators=[], drop_down=drop_down, image=None) relations = list(fieldset[1].get('relations', [])) inlines = list(fieldset[1].get('inlines', [])) if tab_name or self.as_pdf: self.fieldsets_with_tab_name.append(fieldset_dict) else: self.fieldsets_without_tab_name.append(fieldset_dict) if 'can_view' in fieldset[1]: can_view = fieldset[1]['can_view'] if not permissions.check_group_or_permission( self.request, can_view): continue if 'image' in fieldset[1]: fieldset_dict['image'] = fieldset[1]['image'] if 'fields' in fieldset[1]: for name_or_tuple in fieldset[1]['fields']: if not type(name_or_tuple) == tuple: name_or_tuple = (name_or_tuple, ) attr_names = [] for attr_name in name_or_tuple: if attr_name != parent and attr_name != fieldset_image: attr = getattr(model, attr_name) field = None if hasattr(attr, 'field_name'): field = getattr(model, '_meta').get_field( attr.field_name) elif hasattr(attr, 'field'): field = attr.field if not field or not hasattr( field, 'display') or field.display: verbose_name, lookup, sortable, to = get_fiendly_name( model, attr_name, as_tuple=True) if to and not should_filter_or_display( self.request, model, to): continue attr_names.append( dict(verbose_name=verbose_name, name=attr_name)) if attr_names: fieldset_dict['fields'].append(attr_names) if self.complete: from djangoplus.utils.relations import Relation for relation_name in relations + inlines: component = Relation(self.obj, relation_name).get_component( self.request, self.as_pdf) fieldset_dict['paginators'].append(component) else: for relation_name in relations + inlines: if relation_name in [ field.name for field in get_metadata(model, 'get_fields') ]: relation_field = find_field_by_name( model, relation_name) if is_one_to_one(model, relation_name) or is_many_to_one( model, relation_name): fieldset_dict['fields'].append([ dict(verbose_name=relation_field. verbose_name, name=relation_name) ]) if 'extra' in fieldset[1]: fieldset_dict['extra'] = [] for info in fieldset[1]['extra']: fieldset_dict['extra'].append(info)
def action(request, app, cls, action_name, pk=None): try: _model = apps.get_model(app, cls) except LookupError: return page_not_found(request) for group in loader.actions[_model]: if action_name in loader.actions[_model][group]: break form_action = loader.actions[_model][group][action_name] action_title = form_action['title'] action_can_execute = form_action['can_execute'] action_condition = form_action['condition'] action_function = form_action['function'] action_message = 'message' in form_action and form_action['message'] or None action_permission = '%s.%s' % (_model._meta.app_label, action_function.func_name) action_input = form_action['input'] redirect_to = form_action['redirect_to'] obj = pk and _model.objects.all(request.user).get(pk=pk) or _model() obj.request = request obj._user = request.user title = action_title if check_condition(action_condition, obj) and (not action_can_execute or permissions.check_group_or_permission( request, action_permission)): func = getattr(_model, action_function.func_name, action_function) form = factory.get_action_form(request, obj, form_action) if func.func_code.co_argcount > 1 or action_input: if form.is_valid(): if 'instance' in form.fields: obj = form.cleaned_data['instance'] func = getattr(obj, action_function.func_name, action_function) params = [] for param in func.func_code.co_varnames[1:func.func_code. co_argcount]: if param in form.cleaned_data: params.append(form.cleaned_data[param]) try: f_return = func(*params) if not redirect_to: if func.func_code.co_argcount > 1: return httprr(request, '..', action_message) else: return httprr(request, '.', action_message) else: return httprr( request, Template(redirect_to).render(Context({'self': obj})), action_message) except ValidationError, e: form.add_error(None, unicode(e.message)) else: try: if form.fields and form.is_valid() or not form.fields: if form.fields: obj = form.cleaned_data['instance'] func = getattr(obj, action_function.func_name, action_function) f_return = func() if not redirect_to: if func.func_code.co_argcount > 1: return httprr(request, '..', action_message) else: return httprr(request, '.', action_message) else: return httprr( request, Template(redirect_to).render(Context({'self': obj})), action_message) except ValidationError, e: return httprr(request, '.', unicode(e.message))
def __init__(self, request, obj, current_tab=None, parent=None, fieldsets=None, complete=True): super(ModelPanel, self).__init__(request=request) self.obj = obj self.request = request self.title = unicode(obj) self.tabs = [] self.current_tab = current_tab self.message = None self.complete = complete self.drop_down = None fieldsets = fieldsets or get_metadata(type(obj), 'view_fieldsets', []) if not fieldsets: fields = [] for field in get_metadata(type(obj), 'fields')[1:]: fields.append(field.name) for field in get_metadata(type(obj), 'local_many_to_many'): fields.append(field.name) fieldsets = ((u'Dados Gerais', dict(fields=fields)), ) if self.complete: self.drop_down = ModelDropDown(self.request, type(self.obj)) self.drop_down.add_actions(self.obj, fieldset_title='') else: self.drop_down = GroupDropDown(self.request) self.fieldsets_with_tab_name = [] self.fieldsets_without_tab_name = [] model = type(self.obj) obj.as_pdf = self.as_pdf for fieldset in fieldsets: title, info = fieldset tab_name = None drop_down = ModelDropDown(self.request, model) fieldset_actions = info.get('actions', []) if fieldset_actions: drop_down.add_actions(self.obj, fieldset_title=title) if '::' in title: tab_name, title = title.split('::') url = '/view/%s/%s/%s/%s/' % (get_metadata( model, 'app_label'), model.__name__.lower(), self.obj.pk, slugify(tab_name)) tab = (tab_name, url) if not self.tabs and not self.current_tab: self.current_tab = slugify(tab_name) if tab not in self.tabs: self.tabs.append(tab) if not tab_name or slugify( tab_name) == self.current_tab or self.as_pdf: fieldset_dict = dict(title=title or u'Dados Gerais', tab_name=tab_name, fields=[], paginators=[], drop_down=drop_down, image=None) relations = fieldset[1].get('relations', []) if tab_name or self.as_pdf: self.fieldsets_with_tab_name.append(fieldset_dict) else: self.fieldsets_without_tab_name.append(fieldset_dict) if 'can_view' in fieldset[1]: can_view = fieldset[1]['can_view'] if not permissions.check_group_or_permission( self.request, can_view): continue if 'condition' in fieldset[1]: condition = fieldset[1]['condition'] self.obj.request = self.request if not check_condition(condition, self.obj): continue if 'image' in fieldset[1]: fieldset_dict['image'] = fieldset[1]['image'] if 'fields' in fieldset[1]: for name_or_tuple in fieldset[1]['fields']: if not type(name_or_tuple) == tuple: name_or_tuple = (name_or_tuple, ) attr_names = [] for attr_name in name_or_tuple: if attr_name != parent: attr = getattr(model, attr_name) field = None if hasattr(attr, 'field_name'): field = getattr(model, '_meta').get_field( attr.field_name) elif hasattr(attr, 'field'): field = attr.field if not field or not hasattr( field, 'display') or field.display: if is_one_to_one( model, attr_name ) and attr.field.display == 'detail': relations.append(attr_name) elif is_one_to_many( model, attr_name ) and field.display == 'detail': relations.append(attr_name) elif is_many_to_one( model, attr_name ) and field.display == 'detail': relations.append(attr_name) elif is_many_to_many( model, attr_name) and ( not hasattr(field, 'display') or field.display == 'detail'): relations.append(attr_name) elif is_one_to_many_reverse( model, attr_name): relations.append(attr_name) else: verbose_name, lookup, sortable, to = get_fiendly_name( model, attr_name, as_tuple=True) if to and not should_filter_or_display( self.request, model, to): continue attr_names.append( dict(verbose_name=verbose_name, name=attr_name)) if attr_names: fieldset_dict['fields'].append(attr_names) if self.complete: for relation_name in relations: if relation_name in [ field.name for field in get_metadata(model, 'get_fields') ]: relation_field = find_field_by_name( model, relation_name) relation = getattr(self.obj, relation_name) if not relation and hasattr( relation_field, 'rel') and relation_field.rel.to: relation = relation_field.rel.to() if hasattr(relation.__class__, 'pk'): if relation.pk: fieldset_title = relation_field.verbose_name panel_fieldsets = get_metadata( type(relation), 'view_fieldsets', []) panel_fieldsets = ( (fieldset_title, panel_fieldsets[0][1]), ) panel = ModelPanel( request, relation, fieldsets=panel_fieldsets, complete=False) if is_one_to_one(model, relation_name): app_label = get_metadata( model, 'app_label') model_name = model.__name__.lower() related_model_name = type( relation).__name__.lower() add_url = '/add/%s/%s/%s/%s' % ( app_label, model_name, self.obj.pk, relation_name) delete_url = None if relation.pk: add_url = '%s/%s/' % (add_url, relation.pk) app_label = get_metadata( type(relation), 'app_label') delete_url = '/delete/%s/%s/%s/' % ( app_label, related_model_name, relation.pk) if permissions.has_add_permission( self.request, model ) or permissions.has_edit_permission( self.request, model): if delete_url: panel.drop_down.add_action( 'Excluir %s' % relation_field. verbose_name, delete_url, 'popup', 'fa-close', None) panel.drop_down.add_action( 'Atualizar %s' % relation_field.verbose_name, add_url, 'popup', 'fa-edit') fieldset_dict['paginators'].append(panel) else: fieldset_title = len( relations ) > 1 and title or relation_field.verbose_name if is_one_to_many( model, relation_name) or is_many_to_many( model, relation_name): to = model.__name__.lower() else: to = relation_name related_paginator = Paginator( self.request, relation.all(), title=fieldset_title, to=to, list_subsets=[]) add_url = '/add/%s/%s/%s/%s/' % (get_metadata( model, 'app_label'), model.__name__.lower( ), self.obj.pk, relation_name) if permissions.has_add_permission( self.request, model ) or permissions.has_relate_permission( self.request, model): related_paginator.add_action( 'Adicionar %s' % unicode( get_metadata( relation.model, 'verbose_name')), add_url, 'popup', 'fa-plus') fieldset_dict['paginators'].append( related_paginator) else: is_object_set = False for related_object in list_related_objects(model): if relation_name == related_object.get_accessor_name( ): is_object_set = True break relation = getattr(self.obj, relation_name) if hasattr(relation, 'all'): qs = relation.all() elif hasattr(relation, '__call__'): qs = relation() else: qs = relation to = is_object_set and related_object.field.name or None fieldset_title = len( relations) > 1 and get_metadata( qs.model, 'verbose_name_plural') or title if hasattr(relation, '_metadata'): fieldset_title = relation._metadata[ '%s:verbose_name' % relation_name] exclude = [ is_object_set and related_object.field.name or '' ] related_paginator = Paginator( self.request, qs, fieldset_title, exclude=exclude, list_subsets=[], to=to, readonly=not is_object_set) if is_object_set and ( permissions.has_add_permission( self.request, qs.model) or permissions.has_relate_permission( self.request, qs.model)): instance = qs.model() setattr(instance, related_object.field.name, self.obj) if permissions.can_add(self.request, instance): add_inline = get_metadata( qs.model, 'add_inline') if add_inline: form_name = get_metadata( qs.model, 'add_form') if form_name: fromlist = get_metadata( qs.model, 'app_label') forms_module = __import__( '%s.forms' % fromlist, fromlist=fromlist) Form = getattr( forms_module, form_name) else: class Form(ModelForm): class Meta: model = qs.model fields = get_metadata( qs.model, 'form_fields', '__all__') exclude = get_metadata( qs.model, 'exclude_fields', ()) submit_label = 'Adicionar' title = u'Adicionar %s' % get_metadata( qs.model, 'verbose_name') form = Form(self.request, instance=instance, inline=True) if related_object.field.name in form.fields: del (form.fields[ related_object.field.name]) related_paginator.form = form if form.is_valid(): try: form.save() self.message = u'Ação realizada com sucesso' except ValidationError, e: form.add_error( None, unicode(e.message)) else: add_url = '/add/%s/%s/%s/%s/' % ( get_metadata(model, 'app_label'), model.__name__.lower(), self.obj.pk, relation_name.replace('_set', '')) add_label = u'Adicionar %s' % get_metadata( qs.model, 'verbose_name') add_label = get_metadata( qs.model, 'add_label', add_label) related_paginator.add_action( add_label, add_url, 'popup', 'fa-plus') fieldset_dict['paginators'].append( related_paginator) if 'extra' in fieldset[1]: fieldset_dict['extra'] = [] for info in fieldset[1]['extra']: fieldset_dict['extra'].append(info)