0
votes

In one of my views I defined a mixin to dynamically set the tech and operator fields of a number of models, including the Client model, based on the user's session details, so that a user didn't need to fill them in manually. This mixin is as follows:

class GetTechMixin(object):
    """
    View mixin that when the form is saved, sets the
    site_user and operator.
    """
    def form_valid(self, form):
        # Get user
        user = self.request.user

        # Get tech for this user
        site_user = SiteUser.objects.get(user=user)

        # Override the tech and operator fields
        form.instance.tech = site_user
        form.instance.operator = site_user.operator

        # Save the object
        self.object = form.save()

        # Return success URL
        return HttpResponseRedirect(self.get_success_url())

I also have the following Tastypie API resource set up with the intention of doing the same thing:

class ClientResource(AbstractModelResource):
    class Meta(AbstractModelResource.Meta):
        queryset = Client.objects.all()
        resource_name = 'client'

    def obj_create(self, bundle, **kwargs):
        # Get tech for this user
        site_user = SiteUser.objects.get(user=bundle.request.user)

        # Override the tech and operator fields
        bundle.obj.tech = site_user
        bundle.obj.operator = site_user.operator

        super(ClientResource, self).obj_create(bundle, **kwargs)

This doesn't seem to work, however. When running it with PDB, I can add the fields to bundle OK, but I when I let it run through it spits out the following error:

{"error_message": "(1048, \"Column 'operator_id' cannot be null\")", "traceback": "Traceback (most recent call last):\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", line 217, in wrapper\n response = callback(request, *args, **kwargs)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", line 459, in dispatch_list\n return self.dispatch('list', request, **kwargs)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", line 491, in dispatch\n response = method(request, **kwargs)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", line 1357, in post_list\n updated_bundle = self.obj_create(bundle, **self.remove_api_resource_names(kwargs))\n\n File \"/home/matthew/Projects/Myproject/app_api/api.py\", line 49, in obj_create\n super(ClientResource, self).obj_create(bundle, **kwargs)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", line 2150, in obj_create\n return self.save(bundle)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/tastypie/resources.py\", line 2296, in save\n bundle.obj.save()\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/models/base.py\", line 546, in save\n force_update=force_update, update_fields=update_fields)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/models/base.py\", line 650, in save_base\n result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/models/manager.py\", line 215, in _insert\n return insert_query(self.model, objs, fields, **kwargs)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/models/query.py\", line 1661, in insert_query\n return query.get_compiler(using=using).execute_sql(return_id)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py\", line 937, in execute_sql\n cursor.execute(sql, params)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/backends/util.py\", line 41, in execute\n return self.cursor.execute(sql, params)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py\", line 127, in execute\n six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py\", line 120, in execute\n return self.cursor.execute(query, args)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/MySQLdb/cursors.py\", line 201, in execute\n self.errorhandler(self, exc, value)\n\n File \"/home/matthew/Projects/Myproject/venv/local/lib/python2.7/site-packages/MySQLdb/connections.py\", line 36, in defaulterrorhandler\n raise errorclass, errorvalue\n\nIntegrityError: (1048, \"Column 'operator_id' cannot be null\")\n"}

I've tried it both with and without bundle.obj.save() after adding the fields and it doesn't seem to make a difference.

Is obj_create the correct place to override these values? If so, can anyone point out where I've goine wrong. If not, where should I be looking?

1
check the value of site_user.operatorkarthikr

1 Answers

1
votes

In case anyone finds this, I found a solution. The easiest thing to do was just to override the obj_create method with a new one as follows:

def obj_create(self, bundle, **kwargs):
    # Get tech for this user
    site_user = SiteUser.objects.get(user=bundle.request.user)

    bundle.obj = self._meta.object_class()

    for key, value in kwargs.items():
        setattr(bundle.obj, key, value)

    # Override the tech and operator fields
    setattr(bundle.obj, 'tech', site_user)
    setattr(bundle.obj, 'operator', site_user.operator)

    self.authorized_create_detail(self.get_object_list(bundle.request), bundle)
    bundle = self.full_hydrate(bundle)
    return self.save(bundle);