我很确定这个问题的答案显然是“不”,因为Django mixins应该是<
继承“对象”,但我无法找到解决问题的替代方案:(
为了使问题尽可能简单,,,
views.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
.....
所以我遇到的问题是,对于多个视图,我想用相同的方式响应他们的“post”请求
JSON回复。这就是为什么我定义了HandlingAJAXPostMixin以便我可以重复使用它为
其他观点。由于HandlingAJAXPostMixin返回JSON响应,
它需要一个render_json_response方法,该方法在JSONResponseMixin中定义。
这就是为什么我让我的HandlingAJAXPostMixin继承了旧的JSONResponseMixin,但这显然是错误的:( ..
有任何建议......?
感谢!!!
答案 0 :(得分:4)
mixin从另一个mixin继承是完全有效的 - 事实上,这就是大多数Django更先进的mixin的制作方式。
然而,mixins的想法是它们是可重用的部分,与其他类一起构建一个完整的,可用的类。现在,您的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提供的那些小的,可重用的方法。这就是你想要的目标。如果尽可能避免/ else逻辑 - Django默认视图中最先进的逻辑是:
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
这就是为什么非常相似的视图,例如CreateView
和UpdateView
实际上是两个独立的视图,而它们可以很容易地成为具有一些额外的if / else逻辑的单个视图。唯一的区别是CreateView
执行self.object = None
,而UpdateView
执行self.object = self.get_object()
。
现在您正在使用DetailView
定义get()
方法,该方法返回self.render_to_response()
的结果。但是,您重写render_to_response()
以返回JSON响应而不是基于模板的HTML响应。你正在使用一个你不使用的mixin(SingleObjectTemplateResponseMixin
),然后覆盖它的行为来做你不想做的事情,只是为了让视图做你想要的做。更好的想法是为DetailView
编写替代方案,他的唯一工作就是根据单个对象提供JSON响应。为此,我将创建一个SingleObjectJSONResponseMixin
,类似于SingleObjectTemplateResponseMixin
,并创建一个类JSONDetailView
,将所有需要的mixin组合到一个对象中:
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
。与UpdateView
混合以轻松创建基于AJAX / JSON的to_json()
。子类可以轻松覆盖mixin的不同部分,例如覆盖render_to_response()
以提供特定的数据结构。渲染逻辑就是它所属的位置(在JSONDetailView
中)。
现在,您只需创建特定的class UserJSONDetailView(JSONDetailView):
model = MyUser
即可创建子类并定义要使用的模型:
{{1}}