开发者

Django(trunk) and class based generic views: one form's initial data appearing in another one's

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',
    ('^$', 'create'),
    (r'^(?P<pk>\d+)/$', 'update'),
)

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


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 


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)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜