Buscar..


Observaciones

Cuando usamos CBV, a menudo necesitamos saber exactamente qué métodos podemos sobrescribir para cada clase genérica. Esta página de la documentación de django enumera todas las clases genéricas con todos sus métodos simplificados y los atributos de clase que podemos usar.

Además, el sitio web Classy Class Based View proporciona la misma información con una interfaz interactiva agradable.

Vistas basadas en clase

Las vistas basadas en clase le permiten concentrarse en lo que hace que sus vistas sean especiales.

Una página estática sobre la página puede no tener nada especial, excepto la plantilla utilizada. Utilice un TemplateView ! Todo lo que tienes que hacer es establecer un nombre de plantilla. Trabajo hecho. Siguiente.

vistas.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'),
]

Observe cómo no utilizamos directamente AboutView en la url. Esto se debe a que se espera una llamada y eso es exactamente lo que as_view() devuelve.

Datos de contexto

A veces, su plantilla necesita un poco más de información. Por ejemplo, nos gustaría tener al usuario en el encabezado de la página, con un enlace a su perfil junto al enlace de cierre de sesión. En estos casos, utilice el método get_context_data .

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

Debe llamar al método get_context_data en la superclase y devolverá la instancia de contexto predeterminada. Cualquier elemento que agregue a este diccionario estará disponible para la plantilla.

libro.html

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

Vistas de lista y detalles

Las vistas de plantilla están bien para la página estática y podría usarlas para todo con get_context_data pero sería apenas mejor que usar la función como vistas.

Ingrese a ListView y DetailView

app / 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)

app / 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

Eso es todo lo que necesita para generar una vista que enumere todos sus objetos de modelos y vistas de un elemento singular. La lista está incluso paginada. Puede proporcionar template_name si desea algo específico. Por defecto, se genera a partir del nombre del modelo.

app / templates / app / 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>

El contexto se rellena con la lista de objetos bajo dos nombres, object_list y una segunda compilación a partir del nombre del modelo, aquí pokemon_list . Si ha paginado la lista, también debe cuidar el enlace anterior y el siguiente. El objeto Paginator puede ayudar con eso, también está disponible en los datos de contexto.

app / templates / app / pokemon_detail.html

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

Como antes, el contexto se completa con su objeto modelo bajo el nombre de object y pokemon , el segundo se deriva del nombre del modelo.

app / 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'),
]

En este fragmento, la url para la vista de detalle se crea utilizando la clave principal. También es posible usar una bala como argumento. Esto da una url más bonita que es más fácil de recordar. Sin embargo, requiere la presencia de un campo llamado slug en su modelo.

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

Si un campo llamado slug no está presente, se puede utilizar el slug_field puesta en DetailView para que apunte a un campo diferente.

Para la paginación, use una página obtener parámetros o poner una página directamente en la url.

Creación de forma y objeto.

Escribir una vista para crear un objeto puede ser bastante aburrido. Debe mostrar un formulario, debe validarlo, debe guardar el elemento o devolver el formulario con un error. A menos que uses una de las vistas de edición genéricas .

app / 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 y UpdateView tienen dos atributos, model y fields requeridos. De forma predeterminada, ambos usan un nombre de plantilla basado en el nombre del modelo con el sufijo '_form'. Solo puede cambiar el sufijo con el atributo template_name_suffix. El DeleteView muestra un mensaje de confirmación antes de eliminar el objeto.

Tanto UpdateView como DeleteView deben DeleteView en el objeto. Utilizan el mismo método que DetailView , extraen la variable de la URL y hacen coincidir los campos del objeto.

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

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

form contiene el formulario con todos los campos necesarios. Aquí, se mostrará con un párrafo para cada campo debido a as_p .

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

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

La etiqueta csrf_token es necesaria debido a la protección de django contra la falsificación de solicitudes. La acción del atributo se deja vacía, ya que la URL que muestra el formulario es la misma que la que maneja la eliminación / guardar.

Dos problemas permanecen con el modelo, si se usa lo mismo que con la lista y el ejemplo de detalle. En primer lugar, crear y actualizar se quejará de una URL de redireccionamiento que falta. Eso se puede resolver agregando un get_absolute_url al modelo pokemon. El segundo problema es que la confirmación de eliminación no muestra información significativa. Para resolver esto, la solución más sencilla es agregar una representación de cadena.

app / 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

El decorador de la clase se asegurará de que todo funcione sin problemas bajo python 2.

Ejemplo minimo

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()),
]

Aprenda más sobre la documentación de Django »

Vistas basadas en la clase de Django: Ejemplo de CreateView

Con las vistas genéricas basadas en clase, es muy simple y fácil crear las vistas CRUD desde nuestros modelos. A menudo, el administrador integrado de Django no es suficiente o no es el preferido y necesitamos rodar nuestras propias vistas de CRUD. Los CBV pueden ser muy útiles en tales casos.

La clase CreateView necesita 3 cosas: un modelo, los campos para usar y la url de éxito.

Ejemplo:

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

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

Una vez que la creación es exitosa, el usuario es redirigido a success_url . También podemos definir un método get_success_url en get_success_url lugar y usar reverse o reverse_lazy para obtener la url de éxito.

Ahora, necesitamos crear una plantilla para esta vista. La plantilla debe tener un nombre en el formato <app name>/<model name>_form.html . El nombre del modelo debe estar en mayúsculas inferiores. Por ejemplo, si el nombre de mi aplicación es dashboard , entonces para la vista de creación anterior, debo crear una plantilla llamada dashboard/campaign_form.html .

En la plantilla, una variable de form contendría el formulario. Aquí hay un código de ejemplo para la plantilla:

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

Ahora es el momento de agregar la vista a nuestros patrones de url.

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

Si visitamos la URL, deberíamos ver un formulario con los campos que elegimos. Cuando lo enviemos, intentará crear una nueva instancia del modelo con los datos y guardarlo. En caso de éxito, el usuario será redirigido a la URL de éxito. En caso de errores, el formulario se mostrará de nuevo con los mensajes de error.

Una vista, formas múltiples

Este es un ejemplo rápido del uso de múltiples formularios en una vista de 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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow