Luke Plant wrote:
> I think the purpose of manipulators is to take the donkey work out
> of updating multiple fields.  If it's only one field, then why bother
> with the manipulator?  Just grab the object, read the request.POST data
> for the one field, update the object and save it.
>       myobject.foo = request.POST["foo"]
>       myobject.save()
>
> The disadvantage with this is you don't get the nice validation stuff
> that manipulators do.  I'm not sure if there is a way to call the
> validators directly.

Yes - this is the most obvious workaround. However, I'm trying to
follow the "django" model and "do the right thing" - i.e. always use
the built-in validators so I can put all my validation stuff in one
place - the model definition.

Here's my current "hack" to use manipulators this way. Works fine but
does have a hack having to do with foriegn keys in the object data that
I'd like to fix:

    try:
        manipulator = customers.ChangeManipulator(c_id)
    except customers.CustomerDoesNotExist:
        raise Http404

    if request.POST:
        # get a copy of the POSTed fields
        new_data = request.POST.copy()

        # the POST dict is a special object so add all the
        # original object data to IT but don't
        # override any key's already in the POST dict

        # get a copy of the original object's data
        obj_data = manipulator.flatten_data()

        # stuff the existing object fields into to
        # POST-ed data's dict if the field is not
        # already present in the POST
        for k,v in obj_data.items():
            if not new_data.has_key(k):
                new_data[k] = nz(v)

        # HACK: have to set any foriegn keys in the object directly to
deal
        # with the issue that they have '_id' at the end
        # of the key name in the dict data, but not in the POST data
        new_data['created_by'] = new_data['created_by_id']

        # check for errors
        errors = manipulator.get_validation_errors(new_data)

        if not errors:
            # save the customer data
            manipulator.do_html2python(new_data)
            manipulator.save(new_data)

            # Do a redirect after post so that browser reload works,
etc.
            return HttpResponseRedirect("/customers/list/")

    else:
        # not a POST of form data - no errors, and copy data from
object
        errors = {}
        new_data = manipulator.flatten_data()

    form = formfields.FormWrapper(manipulator, new_data, errors)

    #...

    return render_to_response(
        'uv2/customers/detail',
        DjangoContext(request, {'form': form}),
    )

This works great and uses the manipulator to validate and update only
the fields found in the POST while defaulting to existing values where
not specified (my goal). However, there's the HACK having to do with
the fact that the flatten_data() function returns foriegn key fields
with the "_id" postfix while these fields are expected in the POST
without, so you have to correct each foriegn key explictly. I'd love it
if someone could point me to a auto-magic way of handling these.

If anyone sees anything I'm missing could bite me later on, please let
me know.

Also, it's inefficient to flatten all the fields and the reconvert all
of them back to python form with the do_html2python.

What would be really nice is some sort of flag or setting for the
ChangeManipulator that says, in essense, "only validate and save fields
actually found in the POSTed data - leave all other existing data
alone" - i.e. default to existing values when a field is not specified
in the POST.

Regards,

Chris

Reply via email to