prawg
prawg

Reputation: 511

Tastypie Accessing Query Before Data Gets Replaced by Request

I am using a PATCH request in tastypie to update a field in my model but when this PATCH goes through I am trying to append the data that is already in the database rather than replacing the value entirely.

Example: In a blog post, a user flags a post as inappropriate. You want to get this user's UserID and append it to a field, flaggedUserID. flaggedUserID will contain this user's ID along with anyone else who has flagged the post previously.

Where I'm struggling is in finding a hook in tastypie through which I can access the query BEFORE the value is copied from the request into the data from the query. I tried the "alter_deserialized_detail_data(self, request, data)" hook but the value has already been replaced in the data parameter that is passed to this function.

Anyone have any suggestions?

Upvotes: 0

Views: 98

Answers (1)

prawg
prawg

Reputation: 511

After reading through the source code of tastypie this is the solution I came to:

The copying of data from the request to the query seems to be happening in the "update_in_place" function. By overriding this function in the following way I was able to accomplish the results I was looking for:

def update_in_place(self, request, original_bundle, new_data):
    """
    Update the object in original_bundle in-place using new_data.
    """

    """Right here I am checking if the parameter flaggedUserID is in the 
    request (PATCH saves request data to request.body).  If this is false then 
    copy the new data into the query, otherwise jump to 
    alter_deserialized_detail_data where I am handling the appending of the data 
    from the request. """

    if 'flaggedUserID' not in request.body:
        original_bundle.data.update(**dict_strip_unicode_keys(new_data))

    # Now we've got a bundle with the new data sitting in it and we're
    # we're basically in the same spot as a PUT request. SO the rest of this
    # function is cribbed from put_detail.
    self.alter_deserialized_detail_data(request, original_bundle.data)
    kwargs = {
        self._meta.detail_uri_name: self.get_bundle_detail_data(original_bundle),
        'request': request,
    }
    return self.obj_update(bundle=original_bundle, **kwargs)

Depending on the objective I would probably recommend cleaning this up a little bit more. I just wanted to show this code in its most basic form without having to post multiple functions and start confusing people.

Upvotes: 1

Related Questions