use*_*270 1 django ajax json django-class-based-views
我很确定这个问题的答案显然是“否”,因为 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
.....
Run Code Online (Sandbox Code Playgroud)
所以我遇到的问题是,对于多个视图,我想用相同的
JSON 响应来响应它们的“post”请求。这就是为什么我定义了 HandlingAJAXPostMixin 以便我可以将它重用于
其他视图。由于 HandlingAJAXPostMixin 返回 JSON 响应,因此
它需要一个 render_json_response 方法,该方法在 JSONResponseMixin 中定义。
这就是为什么我让 HandlingAJAXPostMixin 继承 JSONResponseMixin 的原因
,但这显然是错误的:(..
有什么建议..?
谢谢!!!
一个 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)
Run Code Online (Sandbox Code Playgroud)
get_object()和get_context_data()是在 的子类中定义的BaseDetailView,但render_to_response()不是。mixins 可以依赖其超类未定义的方法,这允许继承自的不同类BaseDetailView提供自己的render_to_response(). 不过,目前 Django 中只有一个子类。
然而,逻辑被尽可能地委托给 mixin 提供的那些小的、可重用的方法。这就是你想要达到的目标。尽可能避免 if/else 逻辑 - Django 默认视图中最高级的逻辑是:
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
Run Code Online (Sandbox Code Playgroud)
这就是为什么非常相似的视图,例如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),然后重写它的行为来执行您不想执行的操作,只是为了让视图执行您希望它执行的操作。更好的想法是编写一个替代方案,让DetailViewwho 唯一的工作就是提供基于单个对象的 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.
"""
Run Code Online (Sandbox Code Playgroud)
请注意,这与Django 提供的BaseDetailView和几乎完全相同。SingleObjectTemplateResponseMixin不同之处在于,您定义了一个post()方法,并且渲染更加简单,只需将上下文数据转换为 JSON,而不是完整的模板渲染。然而,逻辑被刻意尽可能地保持简单,并且尽可能地分离彼此不依赖的方法。通过这种方式,SingleObjectJSONResponseMixin可以轻松地混合BaseUpdateView创建基于 AJAX/JSON 的UpdateView. 子类可以轻松地覆盖 mixin 的不同部分,例如覆盖to_json()以提供某种数据结构。渲染逻辑是它所属的地方(在render_to_response())。
现在,创建特定模型所需要做的JSONDetailView就是子类化并定义要使用的模型:
class UserJSONDetailView(JSONDetailView):
model = MyUser
Run Code Online (Sandbox Code Playgroud)