0

I'm fairly new to both Python and Django, and I'm in the process of building a small website. I've been experimenting with a dynamic form containing a ModelChoiceField constructed from a QuerySet that is determined by user input. The approach described here works well for me, but I run into trouble if I try to dynamically create a type that inherits from a class that I define within the same file. The reason I tried to do this was that I wanted to override the default form field order by setting the form's fields.keyOrder property.

This is how I tried to do it:

from django import forms

class AbstractForm(forms.Form):
    def __init__(self, *args, **kwargs):
        super(AbstractForm, self).__init__(*args, **kwargs)
        self.fields.keyOrder = ['choices', 'second', 'third']

class ConcreteFormFactory(object):
    @staticmethod
    def generate(queryset):
        properties = {
            'second': forms.CharField(),
            'third': forms.CharField(),
            'choices': forms.ModelChoiceField(queryset=queryset)
        }
        return type('ConcreteForm', (AbstractForm,), properties)

However, when I import ConcreteFormFactory in my view and attempt to call its generate() method, I get a NameError telling me that AbstractForm is not defined. I tried importing AbstractForm into the calling context, but to no avail. Since I wasn't able to get this approach to work, I accomplished my goal another way, but I would still like to understand the scoping issue here. How do I make my dynamic class aware of other classes defined in the same file where I create it? This is on Django 1.2 and Python 2.7.1 (I know that's a very old version of Django).

6
  • It should work like this. Can you post the traceback of that NameError? Commented Dec 27, 2013 at 0:25
  • Why have you set generate(queryset) to a static method? This may be the issue as static methods are called differently against the class instead of the instance object. Commented Dec 27, 2013 at 0:52
  • But @staticmethod shouldn't change how name lookups are done, right? Something like class A(object): pass, class AFactory(object): @staticmethod def makeA(): return type('A', (A,), {}) works fine for me Commented Dec 27, 2013 at 1:03
  • Well that figures...I implemented my generic test code that I posted here and it worked. Then I refactored my real code to use this pattern and it worked. I must have had something else wrong. Sorry everybody! Commented Dec 27, 2013 at 1:06
  • But did you import it from another module? I didn't try that, but it just seems strange to me. I could be way off base here. Commented Dec 27, 2013 at 1:07

1 Answer 1

1

I apologize--this code DOES work as intended. I refactored my real code to use this pattern, and this time it worked. I must have had something else wrong.

Sign up to request clarification or add additional context in comments.

2 Comments

please close your question if it is not going to be helpful for others
Sorry, it won't let me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.