Exemple #1
0
 def get_args_by_view(cls, view):
     args = super(ModelMixin, cls).get_args_by_view(view)
     if view is view_class and extra_args is not None:
         args.update({
             arg_key: call_if(arg_value, cls)
             for (arg_key, arg_value) in extra_args.items()
         })
     return args
Exemple #2
0
def make_model_mixin(view_class,
                     extra_args=None,
                     extra_funcs=None,
                     instance_view=False,
                     no_auto_view_mixin=False):
    """Return a generated Model mixin for a given view HAHA.

    :param view: View to use for this mixin
                 (this view should subclass ``ModelActionMixin``)
    :type view: django.views.generic.View

    :param extra_args: Dictionary of keyword arguments for the view
                       (the dict value is the argument value,
                       and might be a callable, and will be
                       called with the model as argument)
    :type extra_args: dict

    :param extra_funcs: Dictionary of functions to add on the model mixin.
                        (the dict key is the function name, and might
                        be a callable, and will be called with view
                        as argument)
    :type extra_funcs: dict

    :param instance_view: Does the view return a Model (List, Create)
                          or an instance of this Model (Detail,
                          Update, Delete) ? If instance, set to True.
    :type instance_view: bool

    :param no_auto_view_mixin: Disable autopatching of view with
                               ``ModelActionMixin``. (When ``view_class``
                               is missing a method or attribute
                               from ``ModelActionMixin``, it is
                               automatically added (and bound if
                               needed). Set this to True to disable
                               this behaviour.)
    :type no_auto_view_mixin: bool

    :return: Model mixin for ``view_class``
    :rtype: subclass of ``AutoPatternsMixin``

    """
    if not no_auto_view_mixin:
        # not inhibiting automatic adding of ModelActionMixin
        # functionality
        view_class = monkeypatch_mixin(view_class, ModelActionMixin)

    class ModelMixin(AutoPatternsMixin):
        """Class mixin created by make_model_mixin, in order to dynamically
        define the needed functions based on the arguments.

        """
        @classmethod
        def get_views(cls):
            views = super(ModelMixin, cls).get_views()
            views.append(view_class)
            return views

        @classmethod
        def get_args_by_view(cls, view):
            args = super(ModelMixin, cls).get_args_by_view(view)
            if view is view_class and extra_args is not None:
                args.update({
                    arg_key: call_if(arg_value, cls)
                    for (arg_key, arg_value) in extra_args.items()
                })
            return args

    def _get_url(obj, *args, **kwargs):
        """Private function, patched as ``get_*_url`` to the model mixin.

        """
        if instance_view or view_class.instance_view:
            kwargs['kwargs'] = kwargs.get('kwargs', {})
            kwargs['kwargs']['pk'] = obj.id

        return reverse(
            obj.get_url_name(view_class, prefix=True),
            *args,
            **kwargs
        )

    _get_url.__doc__ = "Get %s URL" % view_class.get_action_name()
    # we make _get_url a class method only at this point to be able
    # to change __doc__
    if not (instance_view or view_class.instance_view):
        _get_url = classmethod(_get_url)

    setattr(ModelMixin,
            'get_%s_url' % view_class.get_underscored_action_name(),
            _get_url)

    def _get_url_name(cls):
        """Private function, patched as ``get_*_url_name`` to the model mixin.

        These functions only return an URL name, and you don't have to
        pass an instance as argument because the instance is not
        included in the return value

        """
        return cls.get_url_name(view_class, prefix=True)

    _get_url_name.__doc__ = "Get %s URL" % view_class.get_action_name()

    # we make _get_url_name a class method only at this point to be able
    # to change __doc__
    _get_url_name = classmethod(_get_url_name)

    setattr(ModelMixin,
            'get_%s_url_name' % view_class.get_underscored_action_name(),
            _get_url_name)

    if extra_funcs:
        for func_name, func in extra_funcs.items():
            func_name = call_if(func_name, view_class)
            setattr(ModelMixin,
                    func_name,
                    func)

    return ModelMixin