1

我很确定这个问题的答案显然是“否”,因为 Django mixins 应该

继承“对象”,但我找不到我的问题的替代解决方案:(

为了使问题尽可能简单,,,

视图.py

class JSONResponseMixin(object):
    def render_to_response(self, context):
        "Returns a JSON response containing 'context' as payload"
        return self.get_json_response(self.convert_context_to_json(context))

    def get_json_response(self, content, **httpresponse_kwargs):
        "Construct an `HttpResponse` object."
        return http.HttpResponse(content,
                                 content_type='application/json',
                                 **httpresponse_kwargs)

    def convert_context_to_json(self, context):
        "Convert the context dictionary into a JSON object"
        # Note: This is *EXTREMELY* naive; in reality, you'll need
        # to do much more complex handling to ensure that arbitrary
        # objects -- such as Django model instances or querysets
        # -- can be serialized as JSON.
        return json.dumps(context)


class HandlingAJAXPostMixin(JSONResponseMixin):
    def post(self, request, *args, **kwargs):
        .....
        data = {'somedata': somedata}

        return JSONResponseMixin.render_json_response(data)


class UserDetailView(HandlingAJAXPostMixin, DetailView):
    model = MyUser
    .....



所以我遇到的问题是,对于多个视图,我想用相同的

JSON 响应来响应他们的“发布”请求。这就是为什么我定义了HandlingAJAXPostMixin,以便我可以将它重用于

其他视图。由于HandlingAJAXPostMixin 返回一个JSON 响应,

它需要一个render_json_response 方法,该方法在JSONResponseMixin 中定义。

这就是我让HandlingAJAXPostMixin继承

JSONResponseMixin的原因,但这显然是错误的:(.. 有

什么建议吗..?

谢谢!!!

4

1 回答 1

5

一个 mixin 从另一个 mixin 继承是完全有效的——事实上,这就是大多数 Django 更高级的 mixin 的制作方式。

然而,mixin 的想法是它们是可重用的部分,与其他类一起构建一个完整的、可用的类。现在,您JSONResponseMixin也可能是一个不继承自的单独类,或者这些方法可能只是模块范围的方法。它绝对有效,没有任何问题,但这不是 mixin 的想法。

如果您查看 Django 的BaseDetailView,您会看到以下get()方法:

def get(self, request, *args, **kwargs):
    self.object = self.get_object()
    context = self.get_context_data(object=self.object)
    return self.render_to_response(context)

get_object()并且get_context_data()在 的子类中定义BaseDetailView,但render_to_response()不是。mixin 可以依赖于它的超类未定义的方法,这允许不同的继承自BaseDetailView的类提供它们自己的render_to_response(). 不过,现在,在 Django 中,只有一个子类。

但是,逻辑尽可能地委托给 mixins 提供的那些小的、可重用的方法。这就是你想要达到的目标。尽可能避免 if/else 逻辑 - Django 默认视图中最高级的逻辑是:

if form.is_valid(): 
    return self.form_valid(form) 
else: 
    return self.form_invalid(form)

这就是为什么非常相似的视图,就像实际上是两个独立的视图,而它们很容易成为带有一些额外 if/else 逻辑的单个视图CreateViewUpdateView唯一的区别是 that CreateViewdoes self.object = None, while UpdateViewdoes self.object = self.get_object()

现在,您正在使用DetailView定义get()返回结果的方法的a self.render_to_response()。但是,您覆盖render_to_response()以返回 JSON 响应而不是基于模板的 HTML 响应。你正在使用一个你不想使用的 mixin ( SingleObjectTemplateResponseMixin) 然后覆盖它的行为来做你不想做的事情,只是为了让视图做你想做的事情。一个更好的主意是编写一个替代方案,因为DetailView他唯一的工作就是提供基于单个对象的 JSON 响应。为此,我将创建一个SingleObjectJSONResponseMixin,类似于SingleObjectTemplateResponseMixin,并创建一个JSONDetailView将所有需要的 mixins 组合到一个对象中的类:

class SingleObjectJSONResponseMixin(object):
    def to_json(context):
        return json.dumps(context)

    def render_to_response(context, **httpresponse_kwargs):
        return HttpResponse(self.to_json(context),
                            context_type='application/json',
                            **httpresponse_kwargs)

class BaseJSONDetailView(SingleObjectMixin, View):
    # if you want to do the same for get, inherit just from BaseDetailView
    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        return render_to_response(context)

class JSONDetailView(SingleObjectJSONResponseMixin, BaseJSONDetailView):
    """ 
    Return JSON detail data of a single object.
    """

请注意,这与Django 提供的BaseDetailView和几乎完全相同。SingleObjectTemplateResponseMixin不同之处在于您定义了一个post()方法,并且渲染要简单得多,只需将上下文数据转换为 JSON,而不是完整的模板渲染。但是,故意使逻辑尽可能简单,并且尽可能将不相互依赖的方法分开。这样,SingleObjectJSONResponseMixin例如可以混合使用BaseUpdateView以轻松创建基于 AJAX/JSON 的UpdateView. 子类可以轻松地覆盖 mixin 的不同部分,例如覆盖to_json()以提供特定的数据结构。渲染逻辑是它所属的地方(在 中render_to_response())。

现在您需要做的就是创建一个特定JSONDetailView的子类并定义要使用的模型:

class UserJSONDetailView(JSONDetailView):
    model = MyUser
于 2013-08-10T13:51:25.287 回答