Django(主干)和基于类的通用视图:一个表单的初始数据出现在另一个表单中

发布于 2024-10-17 11:17:28 字数 2105 浏览 3 评论 0原文

我遇到了一个奇怪的问题,数据似乎在不同的视图和请求中持续存在,直到服务器重新启动。

我已设法将问题减少为以下代码:

# foobar/models.py
from django.db import models

class Foo(models.Model):
    bug = models.CharField(max_length=10)


# foobar/forms.py
from django import forms
from foobar.models import Foo

class CreateForm(forms.ModelForm):
    class Meta:
        model = Foo

class UpdateForm(forms.ModelForm):
    class Meta:
        model = Foo

    def __init__(self, *args, **kwargs):
        kwargs.setdefault('initial', {})
        kwargs['initial'].update({'bug': 'WHY??'})
        super(UpdateForm, self).__init__(*args, **kwargs)


# foobar/views.py
from django.views.generic.edit import CreateView, UpdateView
from foobar.forms import CreateForm, UpdateForm
from foobar.models import Foo

class FooCreateView(CreateView):
    form_class = CreateForm
    template_name = 'foobar/foo_form.html'

create = FooCreateView.as_view()

class FooUpdateView(UpdateView):
    form_class = UpdateForm
    template_name = 'foobar/foo_form.html'
    queryset = Foo.objects.all()

update = FooUpdateView.as_view()


# foobar/urls.py
from django.conf.urls.defaults import *

urlpatterns = patterns('foobar.views',
    ('^$', 'create'),
    (r'^(?P<pk>\d+)/$', 'update'),
)

您还应该添加一个模板(例如在 foobar/templates/foo_form.html 中):

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

要重现,请执行以下操作:

  • 添加 foobar应用程序到 settings.INSTALLED_APPS
  • 运行 syncdb
  • foobar.urls 添加到您的根 urlconf
  • 导航到 /foobar/ (实际的 URL 将取决于您的根 urlconf)
  • 提交表单(从而创建一个新的 Foo 对象)
  • 导航到 /foobar/1/。请注意,表单字段已预先填充(这是预期的)
  • 导航到 /foobar/。请注意,表单字段仍然被填充(这不是预期的)。

这是一个错误还是我做了一些我不应该做的事情(或者也许两者都是......)?

-- 编辑 --

在 forms.py 中,如果我将 update 调用替换为:

kwargs['initial']['bug'] = 'WHY???'

那么问题仍然存在。

注释掉该行可以消除问题(但显然,表单没有初始数据)。

I've run into a strange problem where data seems to persist accross different views and requests until the server gets restarted.

I've managed to reduce the issue to the following code:

# foobar/models.py
from django.db import models

class Foo(models.Model):
    bug = models.CharField(max_length=10)


# foobar/forms.py
from django import forms
from foobar.models import Foo

class CreateForm(forms.ModelForm):
    class Meta:
        model = Foo

class UpdateForm(forms.ModelForm):
    class Meta:
        model = Foo

    def __init__(self, *args, **kwargs):
        kwargs.setdefault('initial', {})
        kwargs['initial'].update({'bug': 'WHY??'})
        super(UpdateForm, self).__init__(*args, **kwargs)


# foobar/views.py
from django.views.generic.edit import CreateView, UpdateView
from foobar.forms import CreateForm, UpdateForm
from foobar.models import Foo

class FooCreateView(CreateView):
    form_class = CreateForm
    template_name = 'foobar/foo_form.html'

create = FooCreateView.as_view()

class FooUpdateView(UpdateView):
    form_class = UpdateForm
    template_name = 'foobar/foo_form.html'
    queryset = Foo.objects.all()

update = FooUpdateView.as_view()


# foobar/urls.py
from django.conf.urls.defaults import *

urlpatterns = patterns('foobar.views',
    ('^

You should also probably add a template (in foobar/templates/foo_form.html for example):

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

To reproduce, do the following:

  • Add the foobar app to settings.INSTALLED_APPS
  • Run syncdb
  • Add foobar.urls to your root urlconf
  • Navigate to /foobar/ (the actual URL will depend on your root urlconf)
  • Submit the form (thus creating a new Foo object)
  • Navigate to /foobar/1/. Notice that the form field is prepopulated (this is expected)
  • Navigate to /foobar/. Notice the form field is still populated (this is not expected).

Is this a bug or am I doing something I shouldn't be (or maybe both...)?

-- EDIT --

In forms.py, if I replace the update call by this:

kwargs['initial']['bug'] = 'WHY???'

Then the problem is still there.

Commenting out the line removes the problem (but then the form has no initial data, obviously).

, 'create'), (r'^(?P<pk>\d+)/

You should also probably add a template (in foobar/templates/foo_form.html for example):


To reproduce, do the following:

  • Add the foobar app to settings.INSTALLED_APPS
  • Run syncdb
  • Add foobar.urls to your root urlconf
  • Navigate to /foobar/ (the actual URL will depend on your root urlconf)
  • Submit the form (thus creating a new Foo object)
  • Navigate to /foobar/1/. Notice that the form field is prepopulated (this is expected)
  • Navigate to /foobar/. Notice the form field is still populated (this is not expected).

Is this a bug or am I doing something I shouldn't be (or maybe both...)?

-- EDIT --

In forms.py, if I replace the update call by this:


Then the problem is still there.

Commenting out the line removes the problem (but then the form has no initial data, obviously).

, 'update'), )

You should also probably add a template (in foobar/templates/foo_form.html for example):

To reproduce, do the following:

  • Add the foobar app to settings.INSTALLED_APPS
  • Run syncdb
  • Add foobar.urls to your root urlconf
  • Navigate to /foobar/ (the actual URL will depend on your root urlconf)
  • Submit the form (thus creating a new Foo object)
  • Navigate to /foobar/1/. Notice that the form field is prepopulated (this is expected)
  • Navigate to /foobar/. Notice the form field is still populated (this is not expected).

Is this a bug or am I doing something I shouldn't be (or maybe both...)?

-- EDIT --

In forms.py, if I replace the update call by this:

Then the problem is still there.

Commenting out the line removes the problem (but then the form has no initial data, obviously).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

糖粟与秋泊 2024-10-24 11:17:28

因为您正在改变传入的 kwargs,这些 kwargs 来自视图类中的类级属性。

相反,复制它们并更新副本:

initial_defaults = {'bug': 'no'}
initial_defaults.update(kwargs.get('initial', {}))
defaults = kwargs.copy()
defaults['initial'] = initial_defaults 

Because you're mutating the kwargs that are passed in, which come from class-level properties in the view class.

Instead, copy them and update the copy:

initial_defaults = {'bug': 'no'}
initial_defaults.update(kwargs.get('initial', {}))
defaults = kwargs.copy()
defaults['initial'] = initial_defaults 
水波映月 2024-10-24 11:17:28

你可能想要指定Django-1.3开发,通用类视图在Django 1.2.5中不存在。在您的 forms.py 文件中,您可以注释以下行并重试吗:

class UpdateForm(forms.ModelForm):
    class Meta:
        model = Foo

    def __init__(self, *args, **kwargs):
        #kwargs.setdefault('initial', {})
        #kwargs['initial'].update({'bug': 'WHY??'})
        super(UpdateForm, self).__init__(*args, **kwargs)

You might want to specify Django-1.3 development, generic class view doesn't exist in Django 1.2.5. In your forms.py file, can you comment the following lines and try again:

class UpdateForm(forms.ModelForm):
    class Meta:
        model = Foo

    def __init__(self, *args, **kwargs):
        #kwargs.setdefault('initial', {})
        #kwargs['initial'].update({'bug': 'WHY??'})
        super(UpdateForm, self).__init__(*args, **kwargs)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文