gpt4 book ai didi

python - 如何让 Django UpdateView 仅在第一次工作?

转载 作者:太空宇宙 更新时间:2023-11-03 20:33:14 25 4
gpt4 key购买 nike

假设我有两个具有多对一关系的对象,例如 CarManufacturer,并且想要捕获 first_car_name Manufacturer 的 >,即制造商制造的第一辆汽车。

我有以下两个模型:

from django.db import models
from django.urls import reverse


class Manufacturer(models.Model):
name = models.CharField(max_length=255)
first_car_name = models.CharField(max_length=255, blank=True)

def get_absolute_url(self):
return reverse('manufacturer-detail', kwargs={'pk': self.id})


class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer', on_delete=models.CASCADE)
name = models.CharField(max_length=255)

以下views.py:

from django.http import HttpResponseRedirect
from django.views.generic import UpdateView
from django.views.generic.detail import DetailView

from myapp.models import Manufacturer, Car


class ManufacturerDetailView(DetailView):
model = Manufacturer


class AddCarView(UpdateView):
model = Manufacturer
fields = ['first_car_name']

def form_valid(self, form):
Car.objects.get_or_create(
name=form.cleaned_data['first_car_name'],
manufacturer=self.object)

self.object.refresh_from_db()
if self.object.car_set.count() == 1:
return super().form_valid(form)

return HttpResponseRedirect(self.get_success_url())

以下urls.py

from django.contrib import admin
from django.urls import path
from myapp import views

urlpatterns = [
path('admin/', admin.site.urls),
path('manufacturer/<int:pk>/', views.ManufacturerDetailView.as_view(), name='manufacturer-detail'),
path('manufacturer/<int:pk>/add-car/', views.AddCarView.as_view(), name='add-car')
]

以及 tests.py 中的以下单元测试:

from django.test import TestCase
from django.urls import reverse

from myapp.models import Manufacturer, Car


class ManufacturerViewTests(TestCase):
def test_add_car(self):
manufacturer = Manufacturer.objects.create(name='Ford')

self.client.post(
reverse('add-car', kwargs={'pk': manufacturer.id}),
data={'first_car_name': 'Model T'})

self.assertEqual(Car.objects.count(), 1)
self.assertEqual(Car.objects.first().name, 'Model T')
self.assertEqual(Car.objects.first().manufacturer, manufacturer)

manufacturer.refresh_from_db()
self.assertEqual(manufacturer.first_car_name, 'Model T')

self.client.post(
reverse('add-car', kwargs={'pk': manufacturer.id}),
data={'first_car_name': 'Focus'})

manufacturer.refresh_from_db()
self.assertEqual(manufacturer.first_car_name, 'Model T')

我注意到当我注释掉该行时

self.objects.refresh_from_db()

在重写的 form_valid() 方法中,测试通过了,但实际上,我收到以下断言错误:

> 
python manage.py test myapp.tests
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F
======================================================================
FAIL: test_add_car (myapp.tests.ManufacturerViewTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/kurtpeek/Documents/myproject/myapp/tests.py", line 20, in test_add_car
self.assertEqual(manufacturer.first_car_name, 'Model T')
AssertionError: '' != 'Model T'
+ Model T

----------------------------------------------------------------------
Ran 1 test in 0.017s

FAILED (failures=1)

我很难确定为什么从数据库刷新模型实例会导致此测试失败,并且无论如何,如果是这种情况,它似乎有点“脆弱”。有什么想法可以解决这个错误吗?

(顺便说一句,我有一个工作实现,相当于 Car 模型的 CreateView ,其 form_valid()方法更新 Manufacturer,但出于一致性原因,我希望这是 Manufacturer 模型的 UpdateView)。

最佳答案

原来,当进入form_valid()方法时,表单数据已经保存到self.object中,但还没有提交到数据库,所以当您运行 self.object.refresh_from_db() 时,在调用 中执行 self.object = form.save() 之前,您会“丢失”表单数据>super().form_valid(form)。我最终采用了不同的方法,将其设为 Carl 模型的模型 View ,而不是 Manufacturer 模型的模型 View 。

关于python - 如何让 Django UpdateView 仅在第一次工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57349802/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com