Простая конвертация представлений на основе функций в представления на основе классов в Django

В этом руководстве я рассмотрю простое приложение для заметок, построенное на основе функциональных представлений (FBV), и преобразую их в представления на основе классов (CBV).

Этот пост будет использован в качестве руководства для учебника на YouTube, поэтому я рекомендую посмотреть полный видеоурок и обратиться к исходному коду.

Наши представления на основе функций

Давайте начнем с краткого обзора представлений, которые мы имеем в настоящее время.

Наш файл представлений содержит представления для выполнения основных CRUD-операций по созданию, чтению, обновлению и удалению заметок.

def TaskList(request):
    if request.method == 'GET':
        tasks = Task.objects.all().order_by('-updated')
        context = {'tasks':tasks}
        return render(request, 'base/index.html', context)

    if request.method == 'POST':
        task = Task.objects.create(
            body=request.POST.get('body')
        )
        task.save()
        return redirect('tasks')

## ------------------------------------------------------

def TaskDetail(request, pk):
    if request.method == 'GET':
        task = Task.objects.get(id=pk)
        context = {'task':task}
        return render(request, 'base/task.html', context)

    if request.method == 'POST':
        task = Task.objects.get(id=pk)
        task.body = request.POST.get('body')
        task.save()
        return redirect('tasks')

## ------------------------------------------------------

def TaskDelete(request, pk):
    task = Task.objects.get(id=pk)

    if request.method == 'POST':
        task.delete()
        return redirect('tasks')

    context = {'task':task}   
    return render(request, 'base/delete.html', context)
Вход в полноэкранный режим Выход из полноэкранного режима

Сохранение необработанных представлений на основе классов

Представления на основе классов имеют определенный уровень сложности не потому, что их сложно использовать, а потому, что для них существует уровень абстракции, который затрудняет понимание того, что именно происходит и что нам нужно сделать, чтобы изменить их. Django предоставляет нам ряд встроенных представлений для использования, что способствует быстрой разработке, но до того, как вы узнаете все тонкости и нюансы представлений, это может запутать вас, поскольку под капотом находится много магии.

Поэтому вместо того, чтобы использовать встроенные представления, я буду делать все по-простому и расширять только базовое представление, которое дает нам Django, и писать всю логику с нуля, чтобы вы могли увидеть, чем представления на основе классов отличаются от представлений на основе функций.

Несколько моментов о представлениях на основе классов

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

Расширение базового класса View

Каждое представление на основе классов расширяет базовый класс View. Поскольку мы не используем никаких других встроенных представлений, убедитесь, что вы импортировали View и передали «View» каждому классу:

from django.views import View
...
class OurView(View):
Вход в полноэкранный режим Выход из полноэкранного режима

Разделение по http-методам

При использовании представлений на основе классов мы разделяем наш код на HTTP-глаголы. Поэтому вместо того, чтобы делать что-то вроде if request.method == 'POST', мы просто изменяем метод post, предоставляемый классом View, и позволяем этому методу позаботиться обо всем, что происходит при запросе post. То же самое относится к запросам get.

Например:

class OurView(View):
    def get(self, request):
        pass

    def post(self, request):
        pass
Войти в полноэкранный режим Выход из полноэкранного режима

Давайте начнем с нашего первого представления.

Представление TaskList

Давайте закомментируем представление TaskList и перестроим его с нуля.

Теперь мы перепишем представление как класс и унаследуем от класса View. Также добавим два метода в этот новый класс (get & post) и обязательно передадим self перед request в каждом методе.

Когда у нас есть класс и два метода, давайте извлечем логику из нашего представления, основанного на функциях, и добавим ее в новый класс в соответствии с каждым методом http следующим образом:

from django.views import View
....
class TaskList(View):

    def get(self, request):
        tasks = Task.objects.all().order_by('-updated')
        context = {'tasks':tasks}
        return render(request, 'base/index.html', context)

    def post(self, request):
        task = Task.objects.create(
            body=request.POST.get('body')
        )
        task.save()
        return redirect('tasks')
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь, чтобы использовать это представление, нам нужно сослаться на класс в urls.py и затем использовать метод as_view().

path('', views.TaskList.as_view(), name="tasks"),
Вход в полноэкранный режим Выйти из полноэкранного режима

И вот так мы преобразовали наше первое представление на основе функций в представление на основе классов!

Представление TaskDetail

Теперь сделаем то же самое для TaskDetail. Опять же, мы закомментируем наше представление, основанное на функциях, и извлечем и разделим всю имеющуюся у нас логику на http-методы.

class TaskDetail(View):
    def get(self, request, pk):
        task = Task.objects.get(id=pk)
        context = {'task':task}
        return render(request, 'base/task.html', context)

    def post(self, request, pk):
        task = Task.objects.get(id=pk)
        task.body = request.POST.get('body')
        task.save()
        return redirect('tasks')
Вход в полноэкранный режим Выход из полноэкранного режима

Затем добавьте as_view() к пути url для вызова этого представления.

path('<str:pk>/', views.TaskDetail.as_view(), name="task"),
Вход в полноэкранный режим Выход из полноэкранного режима

ЗадачаУдаление представления

На этом этапе, я уверен, вы начинаете видеть закономерность, поэтому давайте сделаем то же самое, что и раньше, с представлением удаления.

class TaskDelete(View):
    def get(self, request, pk):
        task = Task.objects.get(id=pk)
        context = {'task':task}   
        return render(request, 'base/delete.html', context)

    def post(self, request, pk):
        task = Task.objects.get(id=pk)
        task.delete()
        return redirect('tasks')
Вход в полноэкранный режим Выход из полноэкранного режима
path('<str:pk>/delete/', views.TaskDelete.as_view(), name="delete"),
Войти в полноэкранный режим Выход из полноэкранного режима

Итак, давайте вспомним, что мы делали.

Для каждого вида мы:

  • Изменили def на class.
  • Расширили базовый класс View.
  • Разделили логику по методам http и добавили self перед запросом
  • Добавлено as_view() к каждому представлению в urls.py.

Оцените статью
devanswers.ru
Добавить комментарий