问题
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?
回答1:
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 .
回答2:
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
ormodel
is required.
If you provideform_class
, it should be adjango.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 standardModelForm
for model.
You see, you can specify the form to use. Maybe this already helps you, but without further information we cannot do more.
来源:https://stackoverflow.com/questions/2376058/django-display-generic-modelform-or-predefined-form