views:

184

answers:

2

I have 3 models with various fields in each. For 2 of the models, I'm fine with using a generic form (through Django's create_object) to request data. I wrote a function that accepts the model name and sends the user to the generic form

url(r'^add_(?P<modelname>\w+)/$', generic_add),

def generic_add(request, modelname):
    mdlnm_model = models.get_model('catalog',modelname)
    return create_object(request,
        model = mdlnm_model,
        template_name = 'create.html',
        post_save_redirect = '/library/',
        extra_context = {'func': 'Create ' + modelname},
        login_required =  'True'
    )

For the 3rd model, I have a ModelForm class defined so that I can omit one of the fields in this model when the user sees the form.

url(r'^create_actor/$', create_object, Actor_Input, name='db_actor_create'),

Actor_Input = {
   'form_class': ActorForm,
   'template_name': 'create.html',
   'post_save_redirect': '/library/',
   'extra_context': {'func': 'Create Actor'},
   'login_required': 'True'
}

class ActorForm(forms.ModelForm):
    class Meta:
          model = Actor
          fields = ('name','age','height','short_description',
                   'long_description')

Is there a way for Django to display the defined ModelForm if it exists but otherwise display the fully generic form if a defined form has not been made? I anticipate creating many more models, and would rather not create a url for every single model that needs to be split out the way Actor is.

So put a different way, I want to alter the generic_add function so it will use the ActorForm (if it exists) but otherwise the generic ModelForm. I know how to check for the existance of the ActorForm class, but what if I want that to be dynamic as well? Something like checking if: modelname + 'Form' exists. I'm unsure how to dynamically send the user to a predefined form if one exists.

Any suggestions? Is there a better way to look at this problem?

A: 

It would be very helpful to see this function you are talking about.
The normal way of using create_object is indeed to specify the model or form that you want to use which would result in three URLs in your case.

From the documentation:

Required arguments:

  • Either form_class or model is required.
    If you provide form_class, it should be a django.forms.ModelForm subclass. Use this argument when you need to customize the model's form. See the ModelForm docs for more information.
    Otherwise, model should be a Django model class and the form used will be a standard ModelForm for model.

You see, you can specify the form to use. Maybe this already helps you, but without further information we cannot do more.

Felix Kling
I revised my question above. But basically, I want to be able to use a form_class if one exists, but otherwise the standard ModelForm
Ed
A: 

Here is how I would probably approach what you are trying to do:

url(r'^add_(?P<model_name>\w+)/$', generic_add),

model_presets = {
    'Actor': {
        'extra_context': {'func': 'Create Actor'},
        'form_class': ActorForm,
        'login_required': True,
        'post_save_redirect': '/library/',
        'template_name': 'create.html'
    },
    'default': {
        'extra_context': {'func': 'Oops, something went wrong if you are seeing \
                                   this, it should have been overwritten!'},
        'form_class': None,
        'login_required': True,
        'model': None,
        'post_save_redirect': '/library/',
        'template_name': 'create.html'
    }
}

def _create_object_conf_helper(request, model_name):
    if model_name in model_presets:
        conf = model_presets[model_name]
    else:
        try:
            named_model = models.get_model('catalog', model_name)
        except:
            # do something here to protect your app!
        conf = model_presets['default']
        conf['model'] = named_model
        conf['extra_context']['func'] = 'Create %s' % model_name
    conf['request'] = request
    return conf

def generic_add(request, model_name):
    return create_object(**_create_object_conf_helper(request, model_name))

I haven't tested this but it should work fine, let me know if it doesn't as I may want to use something similar in my own projects down the road.

Additionally you could also take this a step further and create another layer to the model_presets dict to allow a similar helper function to create configs for any other generic views you may be using.

BTW, it isn't necessary to enclose True in quotes, just remember to capitalize the T and not the rue and it will resolve to the 1 bit boolean constant. Using 'True' uses a (rough) minimum of 32 bits as a string. Both will test true in an if statement and thus this it isn't that big of a deal. On the other hand using 'False' won't work as expected as once again this is a string not a boolean and thus will also test as true.

See http://docs.python.org/library/stdtypes.html#truth-value-testing .

Beau