Иногда в джанге нужно сделать так, чтобы одна и та же вьюшка обрабатывала и обычные запросы из браузера и аяксовые.

Например, если мы выводим страницу со статьям, а потом даем возможность при нажатии кнопки подгрузить еще.

Можно сделать разделение логики внутри функции. Например так:


def article_index():
    if request.is_ajax():
        # Может подгружаться AJAX'ом, поэтому в этом случае рендерим ее отдельно, и передаем
        context = {
            'expert': expert,
            'reply_form': reply_form,
            'gallery_form': gallery_form,
        }

        return render(request, 'experts/snippets/answer_form.html', context)

    
    # не аякс
    context = {}
    return render(request, 'experts/form.html', context)

Но если есть возможность использовать class based view, то я предпочитаю сделать для аяксовой логики отдельную функцию.

А направить к ней запрос можно, если переписать dispatch.


class ArticleListView(ListView):
    template = 'obed/article/index.html'
    ajax_template = 'obed/article/article_list.html'

    def dispatch(self, request, *args, **kwargs):
        if request.is_ajax():
            return self.ajax_get(request, *args, **kwargs)

        return super(ListView, self).dispatch(request, *args, **kwargs)

    def ajax_get(self, request, *args, **kwargs):
        # аяксовый запрос
        context = self._make_context()
        return render(request, self.ajax_template, context)

    def get(self, request, *args, **kwargs):
        # обычный
        context = self._make_context()
        return render(request, self.template, context)
        

Отдельная функция лучше, потому что такой код проще читать.