views:

48

answers:

2

I have a page which displays a form that a logged-in user can use to edit their profile.

The first time the user loads the corresponding view, with a GET request, the form should display the values of the users existing profile record.

Because I'd like to have granular control over the markup used for the form fields, I'd like to retrieve the field values only, and manually write the necessary input element markup inserting the retrieved field values as the input elements' 'value' attribute (rather than have django render the entire input elements).

So far I've been trying to use directives like {{ form.myfield.data }} in my template to access the field data, but this is returning "None", instead of the profile details as i expected.

If the user has just posted a valid form though, the form fields do contain the expected profile details.

I hope someone can help me understand what i'm doing wrong here:

Here's my view:

@login_required
def edit(request):
    # get logged-in user's profile
    obj=Profile.objects.get(user=request.user)
    if request.method == 'POST': # If the form has been submitted...
        form = ProfileForm(request.POST, request.FILES, instance=obj)   
        if form.is_valid(): # All validation rules pass
            form.save()
            request.flash['success'] = "Your profile has been updated." # Puts a string to the flash scope
        else:
            request.flash['error'] = 'Please correct the problems below and try again' # Puts a string to the flash scope
    else:
        # if no form was submitted
        # derive the form data from the logged-in users existing profile
        form = ProfileForm(instance=obj)    
    return render_to_response('app_profile/edit.html',
    {
    'form': form,
    'user': request.user,
    'ancestor_urls': ['app_profile.views.edit',],
    },context_instance=RequestContext(request)
)

And here's an excerpt from the corresponding template. This input element deals with a field called 'display_name'.

<input type="text"
class="textInput large {% if form.display_name.errors %}error{% endif %}"
maxlength="50"
size="35"
value="{{ form.display_name.data }}"
id="id_display_name"
name="display_name">
+1  A: 

The way to do what you want to do is to write custom form widgets, instead of doing that in the template.

You can either create an entirely custom widget, or you can just add/change the attributes on the form level when you init the ModelForm

Issac Kelly
Thanks. I get the impression that writing a custom widget is the best option for ease of maintenance. What I'm having trouble with at the moment is understanding how to access a field's errors object from within the custom widget code.
bitbutter
The errors would be set by the form field's validation function. the widget is the markup and css, the form field is the logic. You can write both.
Issac Kelly
A: 

I guess you can solve some of your problems without making a custom widget using the widgets attrs argument: http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.Widget.attrs, also you have some styling options using the input's id!

lazerscience