def response_delete(self, request, instance): """ Return the response when an object has been successfully deleted """ self.add_message(request, 'object_deleted') url = tryreverse('%s_%s_list' % app_model_label(self.model)) return HttpResponseRedirect(url if url else '../../')
def _fn( name, _sentinel=None, view=None, url=None, mixins=None, decorators=None, **kw): if _sentinel is not None: raise TypeError('name is the only non-keyword') urlregex = ( r'^%s/%s/$' % (urlconf_detail_re, name) if url is None else url ) urlname = '%s_%s_%s' % (app_model_label(model) + (name,)) mixins = global_mixins if mixins is None else mixins decorators = global_decorators if decorators is None else decorators kws = kwargs.copy() kws.update(kw) view = default_view_classes[name] if view is None else view view = type(view.__name__, mixins + (view,), {}) view = view.as_view(model=model, **kws) for dec in reversed(decorators): view = dec(view) return _url(urlregex, view, name=urlname)
def response_adding_denied(self, request): """ Return the response when adding instances is denied """ self.add_message(request, 'adding_denied') url = tryreverse('%s_%s_list' % app_model_label(self.model)) return HttpResponseRedirect(url if url else '../../')
def render(self, name, value, attrs=None, **kwargs): active_set = self.model.objects.active_set( self.request.access, additional_ids=filter(None, [ value, self.request.POST.get(name), self.request.GET.get(name), ]), ) self.choices = BLANK_CHOICE_DASH + [(item.id, force_text(item)) for item in active_set] html = super(SelectWithPicker, self).render(name, value, attrs=attrs, **kwargs) picker = reverse('%s_%s_picker' % app_model_label(self.model)) return mark_safe(_PICKER_TEMPLATE % { 'select': html, 'picker': picker, 'field': attrs['id'], })
def get_extra_context(self, request): """ Returns a context containing the following useful variables: * ``verbose_name`` * ``verbose_name_plural`` * ``list_url`` * ``add_url`` * ``base_template`` * ``adding_allowed`` * ``search_form`` (if ``search_form_everywhere = True``) """ info = app_model_label(self.model) return { 'verbose_name': self.model._meta.verbose_name, 'verbose_name_plural': self.model._meta.verbose_name_plural, 'list_url': tryreverse('%s_%s_list' % info), 'add_url': tryreverse('%s_%s_add' % info), 'base_template': self.base_template, 'adding_allowed': self.adding_allowed(request), 'search_form': ( self.search_form(request.GET, request=request) if self.search_form_everywhere else None), 'request': request, # Something changed with Django 1.10's # context processors... }
def handle_batch_form(self, request, ctx, queryset): """ May optionally return a HttpResponse which is directly returned to the browser """ if not self.batch_form: return form = self.batch_form(request, queryset) ctx['batch_form'] = form if form.should_process(): result = form.process() if isinstance(result, HttpResponse): return result elif hasattr(result, '__iter__'): messages.success( request, _('Processed the following items: <br>\n %s') % ( '<br>\n '.join( force_text(item) for item in result))) elif result is not None: # Not None, but cannot make sense of it either. raise TypeError('Return value %r of %s.process() invalid.' % ( result, form.__class__.__name__, )) url = tryreverse('%s_%s_list' % app_model_label(self.model)) return HttpResponseRedirect(url if url else '.')
def api_reverse(model, ident, api_name='api', fail_silently=False, **kwargs): """ Determines the canonical URL of API endpoints for arbitrary models ``model`` is the Django model you want to use, ident should be one of ``list``, ``set`` or ``detail`` at the moment, additional keyword arguments are forwarded to the ``django.core.urlresolvers.reverse`` call. Usage:: api_reverse(Product, 'detail', pk=42) Passing an instance works too:: api_reverse(instance, 'detail', pk=instance.pk) """ try: return reverse( '_'.join( (api_name,) + app_model_label(model) + (ident,)), kwargs=kwargs) except NoReverseMatch: if fail_silently: return None raise
def get_urls(self): """ Return all URLs known to this ``ModelView``. You probably do not need to override this except if you need more granular view decoration than offered with ``view_decorator`` and ``crud_view_decorator``. If you need additional URLs, use ``additional_urls`` instead. """ from django.conf.urls import url info = app_model_label(self.model) urlpatterns = [ url(r"^$", self.view_decorator(self.list_view), name="%s_%s_list" % info), url( r"^add/$", self.crud_view_decorator(self.add_view), name="%s_%s_add" % info, ), url( r"^%s/edit/$" % self.urlconf_detail_re, self.crud_view_decorator(self.edit_view), name="%s_%s_edit" % info, ), url( r"^%s/delete/$" % self.urlconf_detail_re, self.crud_view_decorator(self.delete_view), name="%s_%s_delete" % info, ), ] for spec in self.additional_urls(): urlp, view = spec[:2] if len(spec) > 2: ident = spec[2] else: ident = view.__name__ urlpatterns.extend( [ url( urlp % {"detail": self.urlconf_detail_re, "ident": ident}, view, name=("%s_%s_%%s" % info) % ident, ), ] ) urlpatterns.append( url( r"^%s/$" % self.urlconf_detail_re, self.view_decorator(self.detail_view), name="%s_%s_detail" % info, ), ) return urlpatterns
def get_urls(self): """ Return all URLs known to this ``ModelView``. You probably do not need to override this except if you need more granular view decoration than offered with ``view_decorator`` and ``crud_view_decorator``. If you need additional URLs, use ``additional_urls`` instead. """ from django.conf.urls import patterns, url info = app_model_label(self.model) urlpatterns = patterns( '', url(r'^$', self.view_decorator(self.list_view), name='%s_%s_list' % info), url(r'^add/$', self.crud_view_decorator(self.add_view), name='%s_%s_add' % info), url(r'^%s/edit/$' % self.urlconf_detail_re, self.crud_view_decorator(self.edit_view), name='%s_%s_edit' % info), url(r'^%s/delete/$' % self.urlconf_detail_re, self.crud_view_decorator(self.delete_view), name='%s_%s_delete' % info), ) for spec in self.additional_urls(): urlp, view = spec[:2] if len(spec) > 2: ident = spec[2] else: ident = view.__name__ urlpatterns += patterns( '', url( urlp % { 'detail': self.urlconf_detail_re, 'ident': ident, }, view, name=('%s_%s_%%s' % info) % ident ), ) urlpatterns += patterns( '', url(r'^%s/$' % self.urlconf_detail_re, self.view_decorator(self.detail_view), name='%s_%s_detail' % info), ) return urlpatterns
def __get__(self, obj, objtype=None): if not hasattr(obj, '_modelviewurls_cache'): kwargs = {} data = self.reverse_args_fn(obj) if isinstance(data, dict): kwargs['kwargs'] = data else: kwargs['args'] = data viewname_pattern = '%s_%s_%%s' % app_model_label(obj) obj._modelviewurls_cache = _MVUHelper(viewname_pattern, kwargs) return obj._modelviewurls_cache
def __init__(self, model, **kwargs): self.model = model for key, value in kwargs.items(): if not hasattr(self, key): raise TypeError('%s() received an invalid keyword %r' % (self.__class__.__name__, key)) setattr(self, key, value) if not hasattr(self.model, 'get_absolute_url'): # Add a simple primary key based URL to the model if it does not # have one yet self.model.get_absolute_url = models.permalink(lambda self: ( '%s_%s_detail' % app_model_label(self), (self.pk, ), {}))
def __init__(self, model, **kwargs): self.model = model for key, value in kwargs.items(): if not hasattr(self, key): raise TypeError('%s() received an invalid keyword %r' % ( self.__class__.__name__, key)) setattr(self, key, value) if not hasattr(self.model, 'get_absolute_url'): # Add a simple primary key based URL to the model if it does not # have one yet self.model.get_absolute_url = lambda self: reverse( '%s_%s_detail' % app_model_label(self), args=(self.pk,), )
def response_add(self, request, instance, *args, **kwargs): regions = {} render( request, "%s/%s_detail.html" % app_model_label(self.parent_class), { "object": getattr(instance, self.parent_attr), "regions": regions }, ) return HttpResponse( json.dumps( changed_regions(regions, ["%s_set" % self.model.__name__.lower()])), content_type="application/json", )
def get_template_names(self): """ Returns a list of template names related to the current model and view: - ``self.template_name`` if it's set. - ``<app_label>/<model_name><template_name_suffix>.html - ``resources/object<template_name_suffix>.html """ names = [ '{0}/{1}{2}.html'.format(*(app_model_label(self.model) + (self.template_name_suffix, ))), 'resources/object{0}.html'.format(self.template_name_suffix), ] if self.template_name: names.insert(0, self.template_name) return names
def response_add(self, request, instance, *args, **kwargs): regions = {} render( request, '%s/%s_detail.html' % app_model_label(self.parent_class), { 'object': getattr(instance, self.parent_attr), 'regions': regions, }, ) return HttpResponse( json.dumps(changed_regions(regions, [ '%s_set' % self.model.__name__.lower(), ])), content_type='application/json', )
def __init__(self, model, **kwargs): self.model = model for key, value in kwargs.items(): if not hasattr(self, key): raise TypeError( "%s() received an invalid keyword %r" % (self.__class__.__name__, key) ) setattr(self, key, value) if not hasattr(self.model, "get_absolute_url"): # Add a simple primary key based URL to the model if it does not # have one yet self.model.get_absolute_url = lambda self: reverse( "%s_%s_detail" % app_model_label(self), args=(self.pk,), )
def get_template_names(self): """ Returns a list of template names related to the current model and view: - ``self.template_name`` if it's set. - ``<app_label>/<model_name><template_name_suffix>.html - ``resources/object<template_name_suffix>.html """ names = [ '{0}/{1}{2}.html'.format( *(app_model_label(self.model) + (self.template_name_suffix,))), 'resources/object{0}.html'.format(self.template_name_suffix), ] if self.template_name: names.insert(0, self.template_name) return names
def response_add(self, request, instance, *args, **kwargs): regions = {} render( request, '%s/%s_detail.html' % app_model_label(self.parent_class), { 'object': getattr(instance, self.parent_attr), 'regions': regions, }, ) return HttpResponse( json.dumps( changed_regions(regions, [ '%s_set' % self.model.__name__.lower(), ])), content_type='application/json', )
def get_template(self, request, action): """ Construct and return a template name for the given action. Example:: self.get_template(request, 'list') returns the following template names for ``auth.User``:: [ 'auth/user_list.html', 'modelview/object_list.html', ] """ return [ '%s/%s_%s.html' % (app_model_label(self.model) + (action,)), 'modelview/object_%s.html' % action, ]
def render(self, name, value, attrs=None, **kwargs): active_set = self.model.objects.active_set( self.request.access, additional_ids=filter(None, [ value, self.request.POST.get(name), self.request.GET.get(name), ]), ) self.choices = BLANK_CHOICE_DASH + [ (item.id, force_text(item)) for item in active_set] html = super(SelectWithPicker, self).render( name, value, attrs=attrs, **kwargs) picker = reverse('%s_%s_picker' % app_model_label(self.model)) return mark_safe(_PICKER_TEMPLATE % { 'select': html, 'picker': picker, 'field': attrs['id'], })
def api_reverse(model, ident, api_name='api', fail_silently=False, **kwargs): """ Determines the canonical URL of API endpoints for arbitrary models ``model`` is the Django model you want to use, ident should be one of ``list``, ``set`` or ``detail`` at the moment, additional keyword arguments are forwarded to the ``django.core.urlresolvers.reverse`` call. Usage:: api_reverse(Product, 'detail', pk=42) Passing an instance works too:: api_reverse(instance, 'detail', pk=instance.pk) """ try: return reverse('_'.join((api_name, ) + app_model_label(model) + (ident, )), kwargs=kwargs) except NoReverseMatch: if fail_silently: return None raise
def register(self, model, view_class=None, canonical=True, decorators=None, prefix=None, view_init=None, serializer=None): """ Registers another resource on this API. The sole required argument is the Django model which should be exposed. The other arguments are: - ``view_class``: The resource view class used, defaults to :class:`towel.api.Resource`. - ``canonical``: Whether this resource is the canonical location of the model in this API. Allows registering the same model several times in the API (only one location should be the canonical location!) - ``decorators``: A list of decorators which should be applied to the view. Function decorators only, method decorators aren't supported. The list is applied in reverse, the order is therefore the same as with the ``@`` notation. If unset, the set of decorators is determined from the API initialization. Pass an empty list if you want no decorators at all. Otherwise API POSTing will have to include a valid CSRF middleware token. - ``prefix``: The prefix for this model, defaults to the model name in lowercase. You should include a caret and a trailing slash if you specify this yourself (``prefix=r'^library/'``). - ``view_init``: Python dictionary which contains keyword arguments used during the instantiation of the ``view_class``. - ``serializer``: Function which takes a model instance, the API instance and additional keyword arguments (accept ``**kwargs`` for forward compatibility) and returns the serialized representation as a Python dict. """ view_class = view_class or Resource view_init = view_init or {} if 'model' not in view_init: if 'queryset' in view_init: view_init['model'] = view_init['queryset'].model else: view_init['model'] = model view = view_class.as_view(api=self, **view_init) name = lambda ident: None if canonical: name = lambda ident: '_'.join( (self.name, ) + app_model_label(model) + (ident, )) if decorators is None: decorators = self.decorators if decorators: for dec in reversed(decorators): view = dec(view) self.resources.append({ 'model': model, 'canonical': canonical, 'prefix': prefix or r'^%s/' % model.__name__.lower(), 'urlpatterns': patterns( '', *[ url(regex, view, data, name=name(suffix)) for regex, suffix, data in view_class.urls ]), }) if serializer: self.serializers[model] = serializer
def __get__(self, obj, objtype=None): viewname_pattern = "%s_%s_%%s" % app_model_label(obj) kwargs = {"kwargs": reverse_kwargs_fn(obj)} helper = obj.__dict__["urls"] = _MRUHelper( viewname_pattern, kwargs) return helper
def register(self, model, view_class=None, canonical=True, decorators=None, prefix=None, view_init=None, serializer=None): """ Registers another resource on this API. The sole required argument is the Django model which should be exposed. The other arguments are: - ``view_class``: The resource view class used, defaults to :class:`towel.api.Resource`. - ``canonical``: Whether this resource is the canonical location of the model in this API. Allows registering the same model several times in the API (only one location should be the canonical location!) - ``decorators``: A list of decorators which should be applied to the view. Function decorators only, method decorators aren't supported. The list is applied in reverse, the order is therefore the same as with the ``@`` notation. If unset, the set of decorators is determined from the API initialization. Pass an empty list if you want no decorators at all. Otherwise API POSTing will have to include a valid CSRF middleware token. - ``prefix``: The prefix for this model, defaults to the model name in lowercase. You should include a caret and a trailing slash if you specify this yourself (``prefix=r'^library/'``). - ``view_init``: Python dictionary which contains keyword arguments used during the instantiation of the ``view_class``. - ``serializer``: Function which takes a model instance, the API instance and additional keyword arguments (accept ``**kwargs`` for forward compatibility) and returns the serialized representation as a Python dict. """ view_class = view_class or Resource view_init = view_init or {} if 'model' not in view_init: if 'queryset' in view_init: view_init['model'] = view_init['queryset'].model else: view_init['model'] = model view = view_class.as_view(api=self, **view_init) name = lambda ident: None if canonical: name = lambda ident: '_'.join( (self.name,) + app_model_label(model) + (ident,)) if decorators is None: decorators = self.decorators if decorators: for dec in reversed(decorators): view = dec(view) self.resources.append({ 'model': model, 'canonical': canonical, 'prefix': prefix or r'^%s/' % model.__name__.lower(), 'urlpatterns': patterns('', *[ url(regex, view, data, name=name(suffix)) for regex, suffix, data in view_class.urls ]), }) if serializer: self.serializers[model] = serializer
def __get__(self, obj, objtype=None): viewname_pattern = '%s_%s_%%s' % app_model_label(obj) kwargs = {'kwargs': reverse_kwargs_fn(obj)} helper = obj.__dict__['urls'] = _MRUHelper( viewname_pattern, kwargs) return helper