2013-08-10 2 views
1

Я довольно уверен, что ответ на этот вопрос, очевидно, «НЕТ», так как Django Примеси должны

Достаточно ли для Django mixin наследовать другой mixin?

наследуют «объект» с, но я не могу найти альтернативное решение моей проблемы :(

Для того, чтобы этот вопрос как можно более простым ,,,

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 
    ..... 



Так проблема у меня в том, что для нескольких представлений, я хочу, чтобы ответить на их «пост» запрос с тем же

ответ JSON. Вот почему я определил HandlingAJAXPostMixin так, чтобы его можно было повторно использовать для

другие виды. Поскольку HandlingAJAXPostMixin возвращает ответ JSON,

для него требуется метод render_json_response, который определен в JSONResponseMixin.

Это причина, почему я делаю мой HandlingAJAXPostMixin наследуют

JSONResponseMixin, но это, очевидно, кажется, неправильно :(..

Любые предложения? ..

Спасибо !!!

+0

Как насчет слияния '' JSONResponseMixin', HandlingAJAXPostMixin' в одну примесь? – falsetru

+0

Почему вы не сохраняете только класс JSONResponseMixin и вызываете каждый метод в любое время, когда хотите. – drabo2005

+0

@ abda2005 Что вы имеете в виду точно ...? – user2492270

ответ

4

Это совершенно действительный для mixin, чтобы наследовать от другого mixin - фактически, именно так сделано большинство продвинутых микшинов Django.

Однако идея mixins состоит в том, ком plete, полезный класс. Прямо сейчас, ваш JSONResponseMixin также может быть отдельным классом, на который вы не наследуете, или методы могут быть просто модульными методами. Это определенно работает, в этом нет ничего плохого, но это не идея mixin.

Если посмотреть на Джанго 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() нет. Для миксинсов хорошо опираться на методы, которые суперклассы не определяют, это позволяет различным классам, которые наследуют от BaseDetailView, предоставить свою собственную реализацию render_to_response(). Сейчас, в Django, есть только один подкласс.

Однако логика делегирована как можно больше тем небольшим многоразовым методам, которые поставляются микстинами. Это то, к чему вы хотите стремиться. Если/еще логика избегать, насколько это возможно - самая передовая логика в представлениях 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 на основе шаблонов. Вы используете миксин, чтобы не использовать (SingleObjectTemplateResponseMixin), а затем переопределить его поведение, чтобы сделать то, что вы не хотите делать, просто чтобы получить представление о том, что вы хотите. Лучшей идеей было бы написать альтернативу для DetailView, кто только задание - предоставить ответ JSON на основе одного объекта. Чтобы сделать это, я хотел бы создать SingleObjectJSONResponseMixin, похожий на SingleObjectTemplateResponseMixin, и создать класс JSONDetailView, который сочетает в себе все необходимые Примеси в единый объект:

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. 
    """ 

Обратите внимание, что это почти точно так же, как BaseDetailView а SingleObjectTemplateResponseMixin от Django. Разница заключается в том, что вы определяете метод post() и что рендеринг намного проще с просто преобразованием в JSON данных контекста, а не с полным преобразованием шаблона. Однако логика намеренно упрощается как можно больше, и методы, которые не зависят друг от друга, разделяются как можно больше. Таким образом, SingleObjectJSONResponseMixin может, например, смешивать с BaseUpdateView, чтобы легко создать AJAX/JSON-based UpdateView. Подклассы могут легко переопределять различные части микшинов, например, переопределять to_json() для обеспечения определенной структуры данных. Логика визуализации находится там, где она принадлежит (в render_to_response()).

Теперь все, что вам нужно сделать, чтобы создать определенный JSONDetailView является подкласс и определить, какую модель использовать:

class UserJSONDetailView(JSONDetailView): 
    model = MyUser 
Смежные вопросы