MySQL On Update not triggering for Django/TastyPie REST API
<p>We have a resource table which has a field <code>last_updated</code> which we setup with mysql-workbench to have the following properties:</p>

<p>Datatype: <code>TIMESTAMP</code></p>

<p>NN (NotNull) is <code>checked</code></p>

<p>Default: <code>CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP</code></p>

<p>When I modify a row through the workbench and apply it, the <code>last_updated</code> field properly updates.</p>

<p>When I use the REST api we've setup, and issue a put:</p>

<pre><code>update = requests.put('http://127.0.0.1:8000/api/resources/16',
            data=json.dumps(dict(status="/api/status/4", timeout=timeout_time)),
            headers=HEADER)
</code></pre>

<p>I can properly change any of the values (including status and timeout, and receive a 204 response), but <code>last_updated</code> does not update.</p>

<p><a href="https://docs.djangoproject.com/en/1.9/ref/models/instances/#how-django-knows-to-update-vs-insert" rel="nofollow">Django's model documentation</a> says in this case it should be sending an <code>UPDATE</code>.</p>

<p>Anyone have and ideas on why it's missing these updates? </p>

<p>I can provide further details regarding our specific Django/tastypie setup, but as long as they are issuing an <code>UPDATE</code>, they should be triggering the databases <code>ON UPDATE</code>.</p>

<p>With the added information from spencer7593's <a href="http://stackoverflow.com/a/39478144/3579910">answer</a>, I was able to track down how to do this through tastypie:</p>

<p>The <code>BaseModelResource.save()</code> (from <code>tastypie/resources.py</code>):</p>

<pre><code>def save(self, bundle, skip_errors=False):
    if bundle.via_uri:
        return bundle

    self.is_valid(bundle)

    if bundle.errors and not skip_errors:
        raise ImmediateHttpResponse(response=self.error_response(bundle.request, bundle.errors))

    # Check if they're authorized.
    if bundle.obj.pk:
        self.authorized_update_detail(self.get_object_list(bundle.request), bundle)
    else:
        self.authorized_create_detail(self.get_object_list(bundle.request), bundle)

    # Save FKs just in case.
    self.save_related(bundle)

    # Save the main object.
    obj_id = self.create_identifier(bundle.obj)

    if obj_id not in bundle.objects_saved or bundle.obj._state.adding:
        bundle.obj.save()
        bundle.objects_saved.add(obj_id)

    # Now pick up the M2M bits.
    m2m_bundle = self.hydrate_m2m(bundle)
    self.save_m2m(m2m_bundle)
    return bundle
</code></pre>

<p>Needs to be overridden in your class, so that you can change the Django <a href="https://docs.djangoproject.com/en/1.9/ref/models/instances/#specifying-which-fields-to-save" rel="nofollow">save()</a>, which has the <code>update_fields</code> parameter we want to modify:</p>

<pre><code>    if obj_id not in bundle.objects_saved or bundle.obj._state.adding:
        bundle.obj.save()
</code></pre>

<p>To, for example:</p>

<pre><code>class ResourcesResource(ModelResource):
    # ...
    def save(self, bundle, skip_errors=False):
        # ...
        if obj_id not in bundle.objects_saved or bundle.obj._state.adding:
            resource_fields = [field.name for field in Resources._meta.get_fields() 
                               if not field.name in ['id', 'last_updated']]
            bundle.obj.save(update_fields=resource_fields)
        # ...
</code></pre>

<p>This properly excludes the <code>last_updated</code> column from the sql <code>UPDATE</code>.</p>

python mysql django mysql-workbench tastypie