tags:

views:

319

answers:

5

Hi there,

i have a simple ModelForm:

class MyForm(ModelForm):

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        del self.fields['name']

As you can see, I try to remove a field from the form's field list (the field definitively exists in the model), but I get an Exception:

TemplateSyntaxError at [..]

Caught an exception while rendering: "Key 'name' not found in Form"

I did not write a custom form, so the template where the error occurs is:

/templates/admin/includes/fieldset.html, error at line 4

Any ideas?

-- UPDATE --

The problem appears only in the admin area.

-- UPDATE 2 --

Maybe a trace dump gives more info:

Original Traceback (most recent call last):
  File "/Library/Python/2.5/site-packages/django/template/debug.py", line 71, in render_node
    result = node.render(context)
  File "/Library/Python/2.5/site-packages/django/template/defaulttags.py", line 155, in render
    nodelist.append(node.render(context))
  File "/Library/Python/2.5/site-packages/django/template/defaulttags.py", line 239, in render
    value = bool_expr.resolve(context, True)
  File "/Library/Python/2.5/site-packages/django/template/__init__.py", line 546, in resolve
    obj = self.var.resolve(context)
  File "/Library/Python/2.5/site-packages/django/template/__init__.py", line 687, in resolve
    value = self._resolve_lookup(context)
  File "/Library/Python/2.5/site-packages/django/template/__init__.py", line 722, in _resolve_lookup
    current = current()
  File "/Library/Python/2.5/site-packages/django/contrib/admin/helpers.py", line 81, in errors
    return mark_safe(u'\n'.join([self.form[f].errors.as_ul() for f in self.fields]).strip('\n'))
  File "/Library/Python/2.5/site-packages/django/forms/forms.py", line 105, in __getitem__
    raise KeyError('Key %r not found in Form' % name)
KeyError: "Key 'name' not found in Form"

In the admin area, I use the Grapelli-Theme. Maybe this has to do with the problem?

+1  A: 

You can use the exclude property to remove fields from a ModelForm

exclude = ('field_name1', 'field_name2,)
Jasconius
I know, but I have to remove fields dynamically.
schneck
A: 

One cause I can think of is if your ModelAdmin class which uses your custom form has conflicting settings. For example if you have also explicitly specified 'name' field within 'fields' or 'fieldsets' of your ModelAdmin.

Béres Botond
no, i had a deeper look in the code, there are no hard references like this.
schneck
A: 

As described in Creating forms from models - Using a subset of fields on the form, there are three ways:

  1. In the model, set editable=false. All forms created from the model will exclude the field.
  2. Define the fields attribute in the Meta inner class to only include the fields you want.
  3. Define the exclude attribute in the Meta inner class to list the fields you don't want.

So if your model has fields field1, field2, and field3 and you don't want field3, technique #2 would look like this:

class MyModelForm(ModelForm):
    class Meta:
        model = MyModel
        fields = ('field1', 'field2')

And technique #3 would look like this:

class MyModelForm(ModelForm):
    class Meta:
        model = MyModel
        exclude = ('field3',)
Selene
As i already wrote in my comment above, I have to remove fields dynamically, means, in the __init__-method. Therefore it's not possible to use the methods you suggested.
schneck
What do you mean by removing the fields "dynamically"?
Selene
@Selene: that means, that the fields that will be displayed (/validated/saved) are determined at runtime, not at design time
schneck
Okay, what are you actually trying to do that you need to change what fields are displayed at runtime?
Selene
In my project, there's a model containing many fields, and for the user, it's possible to select a subset of fields that he needs. That already works fine except the annoying problem in the admin backend.
schneck
A: 

Magically™ it works now, although I don't know why. Thanks anyway for your help.

schneck
+1  A: 

I had the same problem. This is how I made it work in the new Django (trunk):

class MyModelAdmin(admin.ModelAdmin):
    # Your stuff here..

    def get_form(self, request, obj=None, **kwargs):
        if request.user.is_staff(): # condition
            self.exclude = ('field',)
        return super(PublishAdmin, self).get_form(request, obj=None, **kwargs)

By overriding the get_form method and putting the logic here you can select which Form you want to have displayed. Above I display the standard form when a condition was met.

wunki