First, I am stuck using django 0.91 because I make extensive use of
model inheritance and how it works in 0.91.

I am wondering how to do something with AddManipulators vs
ChangeManipulators.  The basic issue is that I have a bunch of models
that have some fields only settable on create vs settable at anytime.

The reason for this is that I am representing objects from another
service using the django framework to provide a better experience when
manipulating that other (non-web based) service.

Some fields on the object, such as its 'name' are only settable on
create.  Fine, so in my models I define those fields as 'editable =
False' (they should not be editable on a page that displays a form
generated from that object's ChangeManipulator.)

Now, in my "create_object" view I thought I was clever by augmenting
the AddManipulator I get back from the module to add in the form
fields that should only be present on 'create' of this object:

-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

############################################################################
#
@login_required
def client_create(request, eng_id):
    """The view that is used to create a client object. It is pretty
simple.
    The biggest trick is that we add to the django provided
AddManipulator
    the fields on the client object that are only settable on create.
We also
    properly flag the fields that are required on create.
    """
    engine = engineinstances.get_object(pk = eng_id)
    manipulator = clients.AddManipulator()

    # We need to add the fields to the manipulator that are only valid
when
    # creating a new client object. (ie: settable on create), and we
must
    # the ones that are required as required (ie: required on create)
    #
    manipulator.fields.extend([
        formfields.TextField(field_name="name", is_required = True,
length=30,
                             maxlength = 1024),

formfields.TextField(field_name="dhcp_client_identifier",length=30,
                             maxlength = 1024),
        formfields.TextField(field_name="hardware_address",length=30,
                             maxlength = 1024),
        ])

    if request.POST:
        # If data was POSTed, we're trying to create a new Client.
        new_data = request.POST.copy()
        new_data['gecko_engine_instance'] = engine.id
        new_data['gecko_locally_modified'] = 'c'

        # If dhcp_client_identifier is not set but hardware address is
then
        # derive the dhcp_client_identifier from the hardware address
        #
        if new_data['dhcp_client_identifier'] == "":
            dhcid = mac_to_dhcid(new_data['hardware_address'])
            new_data['dhcp_client_identifier'] = dhcid

        print "Post is: %s\nNew data is: %s" % (str(request.POST),
                                                str(new_data))

        errors = manipulator.get_validation_errors(new_data)
        if not errors:
            # No errors. This means we can save the data!
            manipulator.do_html2python(new_data)
            new_obj = manipulator.save(new_data)
            # Redirect to the object's "edit" page. Always use a
redirect
            # after POST data, so that reloads don't accidently create
            # duplicate entries, and so users don't see the confusing
            # "Repost POST data?" alert box in their browsers.
            return HttpResponseRedirect(new_obj.get_absolute_url())
        else:
            print "client create had errors: %s" % errors
    else:
        # No POST, so we want a brand new form without any data or
errors.
        errors = {}
        new_data = {}

    # Create the FormWrapper, template, context, response.
    form = formfields.FormWrapper(manipulator, new_data, errors)
    t = template_loader.get_template('dcs/client_create')
    c = Context(request, {
        'engine'          : engine,
        'form'            : form,
        'obj_type'        : Client.__name__,
        })
    return HttpResponse(t.render(c))

-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The bits where I do:

        new_data['gecko_engine_instance'] = engine.id
        new_data['gecko_locally_modified'] = 'c'

is because I am creating a new object, and setting one field (that is
a ForeignKey) to the object it points to. The other field is also set
to indicate that I hae 'created' this object locally. These two fields
are marked 'editable = True' because that was the only way to get them
INTO the new object. This is rather hackish though.

The issue is that this does not work. Since the 'name',
'dhcp_client_identifier', and 'hardware_address' fields are not marked
as "editable" in the object model, they are NOT copied from the data
in the HTML form.

It was annoying to find out that 'editable' had this somewhat obscure
meaning.

Now, I could mark them 'editable' and then things would work
here. However, in the "change" form where you can modify an object I
would need to add lines like

        new_data['name'] = orig_obj.name

where "orig_obj" is the original object retrieved from the
ChangeManipulator. If I had to do that then I would have to write
every change view such that it knew which fields were only settable on
create. I could do this. All this information is actually derived
programmatically from a series of XML schemas describing the object
data formats. However that is a bit annoying.

I am wondering if there is a simple, safe, way to add code to the view
that uses the AddManipulator so that these fields I have added to the
form get copied over to the new object being created.

I guess the gist is I can think of some ways to do this. Some seem
more hackish then others. Having stuff that derives data from a
programmatically generated dictionary that tells me which feels to add
to the django created AddManipulator seems a lot simpler then adding
code that knows how to fill these fields in after the form is posted
in the ChangeManipulator. Another option is to perhaps sub-class and
replace somehow the django generated AddManipulator to use some other
source for which fields should be copied over from the form to the
object _before_ the object is saved to the db.

Oh, one thing I forgot to mention - the problem happens in the
AddManipulator's "obj.save()" that is called early on, because the
"name" field is defined as needing to be not-null. This is because
strictly speaking in terms of the data I am representing it should
never be null. THe reason it is null at the tim eof the "obj.save()"
call is because the data is not copied over the data in the form those
fields not marked editable, yada yada.

I could make the field allowed to be null, but the data purist in my
is not happy with that solution because that field should never be
null, even if it is for a short while, and for a number of good
reasons I do not want to weaken this aspect of the data model.

If there is a fantastic way to do this in the magic-removal mainline I
would probably figure out how to jury-rig my models so that I could
deal with the current lack of sub-classing support.

I am looking for some insight in to how this sort of thing should be
resolved. Multiple suggestions are appreciate.

--Scanner


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-users
-~----------~----~----~----~------~----~------~--~---

Reply via email to