Поиск…


замечания

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

Кроме того, сайт Classy Class Based View предоставляет ту же информацию с приятным интерактивным интерфейсом.

Классные представления

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

Статическая страница может не иметь ничего особенного, кроме используемого шаблона. Используйте TemplateView ! Все, что вам нужно сделать, это установить имя шаблона. Работа выполнена. Следующий.

views.py

from django.views.generic import TemplateView


class AboutView(TemplateView):
    template_name = "about.html"

urls.py

from django.conf.urls import url
from . import views

urlpatterns = [
    url('^about/', views.AboutView.as_view(), name='about'),
]

Обратите внимание, что мы не используем напрямую AboutView в URL- AboutView . Это потому, что ожидается вызываемый, и именно это as_view() .

Контекстные данные

Иногда вашему шаблону требуется немного больше информации. Например, мы хотели бы, чтобы пользователь в заголовке страницы со ссылкой на свой профиль рядом с линией выхода. В этих случаях используйте метод get_context_data .

views.py

class BookView(DetailView):
    template_name = "book.html"

    def get_context_data(self, **kwargs)
        """ get_context_data let you fill the template context """
        context = super(BookView, self).get_context_data(**kwargs)
        # Get Related publishers
        context['publishers'] = self.object.publishers.filter(is_active=True)
        return context

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

book.html

<h3>Active publishers</h3>
<ul>
  {% for publisher in publishers %}
    <li>{{ publisher.name }}</li>
  {% endfor %}
</ul>

Просмотр списка и сведений

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

Введите ListView и DetailView

Приложение / models.py

from django.db import models

class Pokemon(models.Model):
    name = models.CharField(max_length=24)
    species = models.CharField(max_length=48)
    slug = models.CharField(max_length=48)

Приложение / views.py

from django.views.generic import ListView, DetailView
from .models import Pokemon


class PokedexView(ListView):
    """ Provide a list of Pokemon objects """
    model = Pokemon
    paginate_by = 25

class PokemonView(DetailView):
    model = Pokemon

Это все, что вам нужно, чтобы создать представление, в котором перечислены все ваши объекты моделей и представления отдельного элемента. Список даже разбит на страницы. Вы можете указать template_name если хотите что-то конкретное. По умолчанию он создается из имени модели.

приложение / шаблоны / приложение / pokemon_list.html

<!DOCTYPE html>
<title>Pokedex</title>
<ul>{% for pokemon in pokemon_list %}
    <li><a href="{% url "app:pokemon" pokemon.pk %}">{{ pokemon.name }}</a>
        &ndash; {{ pokemon.species }}
</ul>

Контекст заполняется списком объекта под двумя именами, object_list и второй object_list из имени модели, здесь pokemon_list . Если вы разместили список страниц, вам необходимо позаботиться о следующей и предыдущей ссылке. Объект Paginator может помочь в этом, он также доступен в контекстных данных.

приложение / шаблоны / приложение / pokemon_detail.html

<!DOCTYPE html>
<title>Pokemon {{ pokemon.name }}</title>
<h1>{{ pokemon.name }}</h1>
<h2>{{ pokemon.species }} </h2>

Как и прежде, контекст заполняется с моделью объекта под именем object и pokemon , второй является производным от названия модели.

Приложение / urls.py

from django.conf.urls import url
from . import views

app_name = 'app'
urlpatterns = [
    url(r'^pokemon/$', views.PokedexView.as_view(), name='pokedex'),
    url(r'^pokemon/(?P<pk>\d+)/$', views.PokemonView.as_view(), name='pokemon'),
]

В этом фрагменте URL-адрес подробного представления создается с использованием первичного ключа. Также возможно использовать slug в качестве аргумента. Это дает более привлекательный URL-адрес, который легче запомнить. Однако для этого требуется наличие поля с именем slug в вашей модели.

url(r'^pokemon/(?P<slug>[A-Za-z0-9_-]+)/$', views.PokemonView.as_view(), name='pokemon'),

Если поле с именем slug отсутствует, вы можете использовать параметр slug_field в DetailView чтобы указать на другое поле.

Для разбивки на страницы используйте страницу для получения параметров или поместите страницу непосредственно в URL-адрес.

Создание формы и объекта

Написание вида для создания объекта может быть довольно скучным. Вам нужно отобразить форму, вы должны ее проверить, вам нужно сохранить элемент или вернуть форму с ошибкой. Если вы не используете одно из общих представлений редактирования .

Приложение / views.py

from django.core.urlresolvers import reverse_lazy
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .models import Pokemon


class PokemonCreate(CreateView):
    model = Pokemon
    fields = ['name', 'species']


class PokemonUpdate(UpdateView):
    model = Pokemon
    fields = ['name', 'species']


class PokemonDelete(DeleteView):
    model = Pokemon
    success_url = reverse_lazy('pokedex')

CreateView и UpdateView есть два обязательных атрибута, model и fields . По умолчанию оба используют имя шаблона, основанное на имени модели, дополненном «_form». Вы можете изменить только суффикс с атрибутом template_name_suffix. Перед удалением объекта DeleteView отображается сообщение с подтверждением.

Оба UpdateView и DeleteView должны извлекать объекты. Они используют тот же метод, что и DetailView , извлекают переменную из url и сопоставляют поля объекта.

app / templates / app / pokemon_form.html (extract)

<form action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Save" />
</form>

form содержит форму со всеми необходимыми полями. Здесь он будет отображаться с абзацем для каждого поля из-за as_p .

app / templates / app / pokemon_confirm_delete.html (extract)

<form action="" method="post">
    {% csrf_token %}
    <p>Are you sure you want to delete "{{ object }}"?</p>
    <input type="submit" value="Confirm" />
</form>

Тег csrf_token требуется из-за защиты django от подделки запроса. Действие атрибута остается пустым, поскольку URL-адрес, отображающий форму, аналогичен тому, который обрабатывает удаление / сохранение.

Остается две проблемы с моделью, если использовать то же самое, что и с примером и подробным примером. Во-первых, создание и обновление будут жаловаться на недостающий URL перенаправления. Это можно решить, добавив get_absolute_url к модели get_absolute_url . Вторая проблема - подтверждение удаления, не отображающее значимой информации. Чтобы решить эту проблему, самым простым решением является добавление строкового представления.

Приложение / models.py

from django.db import models
from django.urls import reverse
from django.utils.encoding import python_2_unicode_compatible


@python_2_unicode_compatible
class Pokemon(models.Model):
    name = models.CharField(max_length=24)
    species = models.CharField(max_length=48)

    def get_absolute_url(self):
        return reverse('app:pokemon', kwargs={'pk':self.pk})

    def __str__(self):
        return self.name

Декоратор класса гарантирует, что все работает плавно под python 2.

Минимальный пример

views.py :

from django.http import HttpResponse
from django.views.generic import View

class MyView(View):
    def get(self, request):
        # <view logic>
        return HttpResponse('result')

urls.py :

from django.conf.urls import url
from myapp.views import MyView

urlpatterns = [
    url(r'^about/$', MyView.as_view()),
]

Подробнее о документации Django »

Django Class Based Views: пример CreateView

Благодаря Generic Views класса, это очень просто и легко создать CRUD-представления из наших моделей. Часто встроенный администратор Django недостаточно или не рекомендуется, и нам нужно перевернуть наши собственные представления CRUD. CBVs могут быть очень удобны в таких случаях.

Для класса CreateView нужны 3 вещи: модель, поля для использования и URL-адрес успеха.

Пример:

from django.views.generic import CreateView 
from .models import Campaign

class CampaignCreateView(CreateView):
    model = Campaign
    fields = ('title', 'description')
    
    success_url = "/campaigns/list"

После успеха создания пользователь перенаправляется на success_url . Мы также можем определить метод get_success_url и использовать reverse или reverse_lazy для получения URL- get_success_url успеха.

Теперь нам нужно создать шаблон для этого представления. Шаблон должен быть назван в формате <app name>/<model name>_form.html . Название модели должно быть в нижних шапках. Например, если мое имя приложения - это dashboard , то для созданного выше представления мне нужно создать шаблон с именем dashboard/campaign_form.html .

В шаблоне переменная form будет содержать форму. Вот пример кода для шаблона:

<form action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Save" />
</form>            

Теперь пришло время добавить представление к нашим шаблонам url.

url('^campaign/new/$', CampaignCreateView.as_view(), name='campaign_new'),

Если мы посетим URL-адрес, мы увидим форму с полями, которые мы выбрали. Когда мы отправляем, он попытается создать новый экземпляр модели с данными и сохранить ее. При успехе пользователь будет перенаправлен на URL-адрес успеха. При ошибках форма снова будет отображаться с сообщениями об ошибках.

Один вид, несколько форм

Ниже приведен краткий пример использования нескольких форм в одном представлении Django.

from django.contrib import messages
from django.views.generic import TemplateView

from .forms import AddPostForm, AddCommentForm
from .models import Comment

class AddCommentView(TemplateView):

    post_form_class = AddPostForm
    comment_form_class = AddCommentForm
    template_name = 'blog/post.html'

    def post(self, request):
        post_data = request.POST or None
        post_form = self.post_form_class(post_data, prefix='post')
        comment_form = self.comment_form_class(post_data, prefix='comment')

        context = self.get_context_data(post_form=post_form,
                                        comment_form=comment_form)

        if post_form.is_valid():
            self.form_save(post_form)
        if comment_form.is_valid():
            self.form_save(comment_form)

        return self.render_to_response(context)     

    def form_save(self, form):
        obj = form.save()
        messages.success(self.request, "{} saved successfully".format(obj))
        return obj

    def get(self, request, *args, **kwargs):
        return self.post(request, *args, **kwargs)


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow