Ejemplo n.º 1
0
 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 '../../')
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
 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 '../../')
Ejemplo n.º 5
0
 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 '../../')
Ejemplo n.º 6
0
    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'],
        })
Ejemplo n.º 7
0
    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...
        }
Ejemplo n.º 8
0
 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 '../../')
Ejemplo n.º 9
0
    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 '.')
Ejemplo n.º 10
0
    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...
        }
Ejemplo n.º 11
0
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
Ejemplo n.º 12
0
    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 '.')
Ejemplo n.º 13
0
    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
Ejemplo n.º 14
0
    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
Ejemplo n.º 15
0
    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
Ejemplo n.º 16
0
    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
Ejemplo n.º 17
0
    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, ), {}))
Ejemplo n.º 18
0
    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,),
            )
Ejemplo n.º 19
0
 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",
     )
Ejemplo n.º 20
0
    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
Ejemplo n.º 21
0
 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',
     )
Ejemplo n.º 22
0
    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,),
            )
Ejemplo n.º 23
0
    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
Ejemplo n.º 24
0
 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',
     )
Ejemplo n.º 25
0
    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,
        ]
Ejemplo n.º 26
0
    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,
        ]
Ejemplo n.º 27
0
    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'],
            })
Ejemplo n.º 28
0
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
Ejemplo n.º 29
0
    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
Ejemplo n.º 30
0
 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
Ejemplo n.º 31
0
    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
Ejemplo n.º 32
0
 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
Ejemplo n.º 33
0
 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