FormView не обновляется, но создает новую запись модели - PullRequest
1 голос
/ 22 января 2020

Я использую представления на основе классов.

Я использую FormView, но открываюсь, чтобы при необходимости перейти на UpdateView.

Моя главная цель состоит в том, чтобы после того, как я получил доступ к своему List (названию модели), я мог при желании изменить его имя.

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

path('lista-detalles/<int:lista_id>/', views.ListDetailsFormView.as_view(), name='list_details'),

В настоящее время мой ListDetailsFormView не обновляется, но создает новую запись.

models.py :

class List(models.Model):
    LISTA_STATUS = (
        ('recibida_pagada', 'Recibida y pagada'),
        ('recibida_no_pagada', 'Recibida pero no pagada'),
        ('en_revision', 'En revision'),
        ('en_camino', 'En camino'),
        ('entregada', 'Entregada'),
        ('cancelada', 'Cancelada')
    )
    name = models.CharField(max_length=100, default='Lista anónima')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    school = models.OneToOneField(School, on_delete=models.CASCADE, null=True, blank=True)
    status = models.CharField(max_length=20, choices=LISTA_STATUS, default='recibida_no_pagada')
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['created_at']

    def __str__(self):
        return str(self.id)

views.py:

from django.shortcuts import get_list_or_404, get_object_or_404
class ListDetailsFormView(LoginRequiredMixin, FormView):
    form_class = ListForm
    template_name = "scolarte/listas/lista-detalles.html"

    def get(self, request, lista_id, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        lista = get_object_or_404(List, id=lista_id)
        data_dict = {'name': lista.name,}
        form = ListForm(initial=data_dict)
        context['form'] = form
        list_items = ListItem.objects.filter(lista=lista)
        context['list_items'] = list_items
        total = 0
        for list_item in list_items:
            total += Decimal(list_item.sub_total())
        context['total'] = total

        return self.render_to_response(context)

    def form_valid(self, lista_id, form):
        # instance = get_object_or_404(List, id=lista_id)
        # form = ListForm(request.POST or None, instance=instance)
        # form = form.save(commit=False)
        # form.user = self.request.user  
        # form.save()
        form.instance.name = self.request.name
        form.save()
        return super(ListDetailsFormView, self).form_valid(form)


    def get_success_url(self):
        return reverse_lazy('lists:list_details', kwargs={'lista_id': self.kwargs['pk']})

БОНУС: Я хочу вернуться на ту же страницу тот, который показывает текущий список и его элементы.

ОБНОВЛЕНИЕ 1:

Я использовал UpdateView, но все же форма создает вместо этого новые объекты обновления.

Просмотр:

class ListDetailsFormView(LoginRequiredMixin, UpdateView):
    model = List
    form_class = ListForm
    context_object_name = 'lista'
    pk_url_kwarg  = 'lista_id'
    template_name = "scolarte/listas/lista-detalles.html"

    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)
        context['list_items'] = ListItem.objects.filter(lista=self.object)
        return context

    def form_valid(self, form):
        form.instance.name = self.request.name
        return super().form_valid(form)

    def get_success_url(self):
        return reverse('lists:list_details', kwargs={'lista_id': self.object.pk})

HTML:

{% extends 'scolarte/base.html' %}

{% load crispy_forms_tags %}

{% block content %}

<!-- <h1>Mi lista: {{ lista.name }}</h1> --> 


<div class="row">
    <form action="{% url 'lists:my_lists' %}" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Submit">
    </form>
</div>



<div class="row">
    {% for list_item in list_items %}
        {% if forloop.counter0|divisibleby:3 and not forloop.first %}<div class="w-100"></div>{% endif %}
        <div class="card margin-right3" style="width: 14rem;">
            <div class="card-body">
              <h5 class="card-title">{{ list_item.product.short_name }}</h5>
              <p class="card-title">$ {{ list_item.product.price }}</p>
              <p class="card-text">{{ list_item.description }}</p>
            </div>
        </div> 
    {% endfor %}
</div>

{% endblock %}

ОБНОВЛЕНИЕ 2:

После обновления ФОРМЫ HTML я получаю:

AttributeError at /listas/lista-detalles/14/
'WSGIRequest' object has no attribute 'name'

html:

<div class="row">
    <form action="{% url 'lists:list_details' lista.id %}" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Submit">
    </form>
</div>

1 Ответ

3 голосов
/ 22 января 2020

Вам нужно пропустить instance при создании формы, но, как говорится, вы можете устранить много шаблонного с помощью UpdateView [Django -док ] :

from django.views.generic.edit import <b>UpdateView</b>

class ListDetailsFormView(LoginRequiredMixin, <b>UpdateView</b>):
    model = List
    form_class = ListForm
    context_object_name = 'lista'
    pk_url_kwarg  = 'lista_id'
    template_name = "scolarte/listas/lista-detalles.html"

    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)
        context['list_items'] = ListItem.objects.filter(lista=self.object)
        return context

    def form_valid(self, form):
        form.instance.name = self.request.name
        return super().form_valid(form)

    def get_success_url(self):
        return reverse('lists:list_details', kwargs={'lista_id': self.object.pk})

Однако, похоже, что у вашего ListForm есть поле name, в этом случае вам вообще не нужно переопределять метод form_valid, и вы это можно использовать:

from django.views.generic.edit import UpdateView

class ListDetailsFormView(LoginRequiredMixin, UpdateView):
    model = List
    form_class = ListForm
    context_object_name = 'lista'
    pk_url_kwarg  = 'lista_id'
    template_name = "scolarte/listas/lista-detalles.html"

    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)
        context['list_items'] = ListItem.objects.filter(lista=self.object)
        return context

    def get_success_url(self):
        return reverse('lists:list_details', kwargs={'lista_id': self.object.pk})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...