tags:

views:

673

answers:

3

I have a form 'in the wild' that takes many different variables - which may or may not be populated.

   try:
        app_version = request.REQUEST["appVersion"]
    except:
        app_version = ''

    try:
        app_name = request.REQUEST["appName"]
    except:
        app_name = ''

    try:
        app_code_name = request.REQUEST["appCodeName"]
    except:
        app_code_name = ''

Is there a tighter way to accomplish this?

+7  A: 
app_version = request.REQUEST.get("appVersion", "")

get(key, default) is a method implemented on Python dicts. If the key exists in the dictionary, its value is returned; if the key does not exist, the specified default value is returned. In Django, request objects are dictionary-like objects, so get is also defined for them in the same manner.

mipadi
This is certainly the most Pythonic answer. I was just about to mark it as 'the' answer but I realized that the answer below takes full advantage of my model definition which is even better than what I had envisioned.
Adam Nelson
+5  A: 

If these variables are intended to populate a form, then you can safely pass the request.POST object directly into the form constructor.

if request.method == 'POST':
    form = MyForm(request.POST)

The form will automatically pass the correct values to the correct form fields and use defaults for keys that don't exist and will still create blank fields for missing keys (see addendum).

If you are trying to process a form, it is still better to create a form object as above, and read out the values from that object.

if request.method == 'POST':
    form = MyForm(request.POST)
    if form.is_valid():
        # You may process these variables here
        print form.appVersion
        print form.appName
        print form.appCodeName

Remember, validation code is best placed in the form class as well. That way, if form.is_valid() returns True, then you know you have a clean dataset to work with.

Note: Django docs recommend using request.POST or request.GET directly rather than the amalgamated variable request.REQUEST, as it is more explicit.

Addendum:

It is important to understand the difference between bound and unbound forms in this case. If you create an unbound form with form = MyForm(), then when the form is instantiated, it will fill in all fields with the initial property of each field (if it exists). For example, with this code:

from django import forms

class MyForm(forms.Form):
    appVersion = forms.CharField(initial='1.0')
    appName = forms.CharField()
    appCodeName = forms.CharField()

the form will be initialized with appVersion having a value of '1.0'. However, if you bind a POST request to a form like this: form = MyForm(request.POST), then the initial properties are ignored. That means if the POST dict does not include an appVersion key, then that field will be left blank. As long as the field is not required, your form will still validate, and you can modify form.appVersion in the view after validation.

sixthgear
and GET request can be validated automatically with url regexes
Evgeny
I wasn't aware of that, thanks!
sixthgear
Great answer.BTW, I will actually use POST, not REQUEST, I just was in test mode and find it easier to send through test cases with GET.
Adam Nelson
It's OK to use GET as well, just test request.method to know which one to handle.
sixthgear
+2  A: 

If you have many fields, a more compact version might be:

defaults = { 'field1' : 'val1', 'field2' : 'val2', ...}
defaults.update(request.POST)
oggy
have to be careful though since it will modify the POST dictionary.
Evgeny
It won't modify the POST dictionary, it will modify the "defaults" dictionary. You then pass the defaults dictionary to the form instead of the POST dict.
oggy