We're using Flask-Restful for implementing an API. As database we use MongoDB and MongoEngine as ODM. To get MongoEngine to work with Restful, we followed this blog article. For getting the correct json-format we using the builtin marsheling-methods. This works perfectly for single objects (e.g. one item of a collection), but when marsheling a list of objects (e.g. all items of a collection), an AttributeError is raised (although we use the same syntax as for single objects). This is how our model and our views look like (I don't paste the routes, as they are in a separate file and work).
model:
class Task(db.Document):
name = db.StringField()
description_mini = db.StringField()
views:
parser = reqparse.RequestParser()
parser.add_argument('task_id', type=str)
task_format = {
"name": fields.String,
"description_mini": fields.String
}
class TasksView(Resource):
#marshal_with(task_format)
def get(self):
tasks = Task.objects().all()
return tasks, 200
class TaskDetailView(Resource):
#marshal_with(task_format)
def get(self):
args = parser.parse_args()
startup_id = args['task_id']
task = Task.objects(id=task_id).first()
return task, 200
full stacktrace:
AttributeError
Traceback (most recent call last)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 257, in error_router
return self.handle_error(e)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 257, in error_router
return self.handle_error(e)
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/project/venv/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 397, in wrapper
resp = resource(*args, **kwargs)
File "/project/venv/lib/python2.7/site-packages/flask/views.py", line 84, in view
return self.dispatch_request(*args, **kwargs)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 487, in dispatch_request
resp = meth(*args, **kwargs)
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 562, in wrapper
return marshal(data, self.fields), code, headers
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 533, in marshal
return OrderedDict(items)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/collections.py", line 52, in __init__
self.__update(*args, **kwds)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_abcoll.py", line 547, in update
for key, value in other:
File "/project/venv/lib/python2.7/site-packages/flask_restful/__init__.py", line 532, in <genexpr>
for k, v in fields.items())
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 104, in output
value = get_value(key if self.attribute is None else self.attribute, obj)
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 37, in get_value
return _get_value_for_keys(key.split('.'), obj, default)
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 42, in _get_value_for_keys
return _get_value_for_key(keys[0], obj, default)
File "/project/venv/lib/python2.7/site-packages/flask_restful/fields.py", line 51, in _get_value_for_key
return obj[key]
File "/project/venv/lib/python2.7/site-packages/mongoengine/queryset/base.py", line 152, in __getitem__
raise AttributeError
AttributeError
When you want to marshal a list you have to define the fields as a list as well.
I think this will work:
task_list_format = {
'tasks': fields.List(fields.Nested(task_format))
}
class TasksView(Resource):
#marshal_with(task_list_format)
def get(self):
tasks = Task.objects().all()
return { 'tasks': tasks }, 200
I believe it is not possible to return a plain list using the marshaling support in Flask-RESTful, it always expects a dictionary. For that reason I put the list under a "tasks" key.
I hope this helps.
From what I understand, the problem is that mongoengine's Queryset object lazily queries the database and that Flask-restful/restplus marshalling expects a list.
I could make it work with
task_format = {
"name": fields.String,
"description_mini": fields.String
}
class TasksView(Resource):
#marshal_with(task_format)
def get(self):
tasks = Task.objects().all()
return list(tasks)
try flask_restful.marshal_with_fields:
>>> from flask_restful import marshal_with_field, fields
>>> #marshal_with_field(fields.List(fields.Integer))
... def get():
... return ['1', 2, 3.0]
...
>>> get()
[1, 2, 3]
Related
I have a model with a field called %_Coverage, and when I try to pass this to .values on a QuerySet, Django throws an error saying "ValueError: unsupported format character '_' (0x5f)". How can I escape the percent sign that it runs correctly?
My_Message = type('My_Message', (models.Model,), {
'__module__': __name__,
'id': models.AutoField(primary_key=True),
'name': 'My_Message',
'%_Coverage': models.IntegerField
})
class Message:
My_Message = models.ForeignKey(My_Message, on_delete=models.CASCADE, null=True, blank=True)
messages = Message.objects.filter(message_name='My_Message').values('My_Message__%_Coverage')
print(messages) # throws an error
# This works:
messages = Message.objects.filter(message_name='My_Message')
print(messages)
# prints: <QuerySet []>
Using f'My_Message__%_Coverage' throws the same error, and 'My_Message__%%_Coverage' complains that the field is not found.
Here is the traceback.
Traceback (most recent call last):
File "python3.8/site-packages/django/core/handlers/base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "python3.8/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "python3.8/site-packages/rest_framework/views.py", line 505, in dispatch
response = self.handle_exception(exc)
File "python3.8/site-packages/rest_framework/views.py", line 465, in handle_exception
self.raise_uncaught_exception(exc)
File "python3.8/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception
raise exc
File "python3.8/site-packages/rest_framework/views.py", line 502, in dispatch
response = handler(request, *args, **kwargs)
File "python3.8/site-packages/rest_framework/decorators.py", line 50, in handler
return func(*args, **kwargs)
File "views/message_viewer.py", line 220, in my_view
print(messages)
File "python3.8/site-packages/django/db/models/query.py", line 263, in __repr__
data = list(self[:REPR_OUTPUT_SIZE + 1])
File "python3.8/site-packages/django/db/models/query.py", line 269, in __len__
self._fetch_all()
File "python3.8/site-packages/django/db/models/query.py", line 1303, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "python3.8/site-packages/django/db/models/query.py", line 111, in __iter__
for row in compiler.results_iter(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size):
File "python3.8/site-packages/django/db/models/sql/compiler.py", line 1108, in results_iter
results = self.execute_sql(MULTI, chunked_fetch=chunked_fetch, chunk_size=chunk_size)
File "python3.8/site-packages/django/db/models/sql/compiler.py", line 1156, in execute_sql
cursor.execute(sql, params)
File "python3.8/site-packages/django/db/backends/utils.py", line 98, in execute
return super().execute(sql, params)
File "python3.8/contextlib.py", line 120, in __exit__
next(self.gen)
File "python3.8/site-packages/django/db/backends/utils.py", line 113, in debug_sql
sql = self.db.ops.last_executed_query(self.cursor, sql, params)
File "python3.8/site-packages/django/db/backends/sqlite3/operations.py", line 160, in last_executed_query
return sql % params
ValueError: unsupported format character '_' (0x5f) at index 83
Here is the relevant code from Django:
# django/db/backends/sqlite3/operations.py
def last_executed_query(self, cursor, sql, params):
# Python substitutes parameters in Modules/_sqlite/cursor.c with:
# pysqlite_statement_bind_parameters(self->statement, parameters, allow_8bit_chars);
# Unfortunately there is no way to reach self->statement from Python,
# so we quote and substitute parameters manually.
if params:
if isinstance(params, (list, tuple)):
params = self._quote_params_for_last_executed_query(params)
else:
values = tuple(params.values())
values = self._quote_params_for_last_executed_query(values)
params = dict(zip(params, values))
return sql % params
# For consistency with SQLiteCursorWrapper.execute(), just return sql
# when there are no parameters. See #13648 and #17158.
else:
return sql
I renamed the field to Percent_Coverage. It seems like a poor idea to have an attribute name with a % sign.
I want to perform a redirect in one of my view, and I'm facing an error with not many details.
My urls.py:
urlpatterns = [
url(
regex=r'^(?P<pk>[0-9]+)/$',
view=views.SheetDetailView.as_view(),
name='detail'
),
url(
regex=r'^(?P<pk>[0-9]+)/branch/(?P<branch_slug>[a-zA-Z0-9-]+)/$',
view=views.SheetDetailView.as_view(),
name='detail'
),
]
My view
class SheetDetailView(LoginRequiredMixin, UserIsLinkedToSheetMixin, UserPassesTestMixin, DetailView):
model = Sheet
def get_context_data(self, **kwargs):
context = super(SheetDetailView, self).get_context_data(**kwargs)
#if no branch is requested, show the master
if 'branch_slug' in self.kwargs:
branch = self.get_object().get_branch(self.kwargs['branch_slug'])
context['branch']=branch
return context
else:
# redirect to master
sheet_id = self.get_object().pk
branch_slug = self.get_object().get_master().slug
return redirect(reverse('sheets:detail', kwargs={'pk':sheet_id, 'branch_slug':branch_slug}), permanent=False)
And my error message:
Traceback (most recent call last):
File "/usr/local/lib/python3.5/site-packages/django/contrib/staticfiles/handlers.py", line 63, in __call__
return self.application(environ, start_response)
File "/usr/local/lib/python3.5/site-packages/django/core/handlers/wsgi.py", line 177, in __call__
response = self.get_response(request)
File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py", line 230, in get_response
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py", line 289, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File "/usr/local/lib/python3.5/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
six.reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.5/site-packages/six.py", line 686, in reraise
raise value
File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py", line 174, in get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py", line 172, in get_response
response = response.render()
File "/usr/local/lib/python3.5/site-packages/django/template/response.py", line 160, in render
self.content = self.rendered_content
File "/usr/local/lib/python3.5/site-packages/django/template/response.py", line 137, in rendered_content
content = template.render(context, self._request)
File "/usr/local/lib/python3.5/site-packages/django/template/backends/django.py", line 92, in render
context = make_context(context, request)
File "/usr/local/lib/python3.5/site-packages/django/template/context.py", line 291, in make_context
context.push(original_context)
File "/usr/local/lib/python3.5/site-packages/django/template/context.py", line 61, in push
return ContextDict(self, *dicts, **kwargs)
File "/usr/local/lib/python3.5/site-packages/django/template/context.py", line 20, in __init__
super(ContextDict, self).__init__(*args, **kwargs)
ValueError: dictionary update sequence element #0 has length 0; 2 is required
When I print out the reverse() result and paste it into my browser, everything is OK.
You're trying to return a redirect from get_context_data. But that method is supposed to return a context for rendering a template, as the name implies. You probably need to put that particular piece of logic in get or dispatch instead.
I am not new to App Engine, but am just getting started with the Python stack on it. I am using webapp2 and Cygwin with its own Python. I am trying to implement custom authentication, relying on sessions.. I am following numerous examples of enabling sessions using webapp2-extras module. I have the following relevant code:
import webapp2
from webapp2_extras import sessions
class BaseHandler(webapp2.RequestHandler):
def dispatch(self):
self.session_store = sessions.get_store(request=self.request)
try:
webapp2.RequestHandler.dispatch(self)
finally:
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def session(self):
return self.session_store.get_session(self.response, backend='datastore')
class CounterHandler(BaseHandler):
def get(self):
cnt_key = 'cnt'
if cnt_key in self.session:
cnt = int(self.session[cnt_key])
else:
cnt = 0
cnt += 1
self.session[cnt_key] = str(cnt)
self.response.headers['Content-Type'] = 'text/plain'
self.response.write("Hello, world!")
This fails with the following stack trace:
Traceback (most recent call last):
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/cygdrive/c/Documents and Settings/dev/My Documents/proj/easytime_gae/src/handlers.py", line 11, in dispatch
self.session_store.save_sessions(self.response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/sessions.py", line 420, in save_sessions
session.save_session(response)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/appengine/sessions_ndb.py", line 117, in save_session
response, self.name, {'_sid': self.sid}, **self.session_args)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/sessions.py", line 423, in save_secure_cookie
value = self.serializer.serialize(name, value)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/securecookie.py", line 48, in serialize
signature = self._get_signature(name, value, timestamp)
File "/cygdrive/c/google_appengine/lib/webapp2-2.5.2/webapp2_extras/securecookie.py", line 103, in _get_signature
signature.update('|'.join(parts))
TypeError: sequence item 0: expected string, Response found
The error goes away if I disable the line that writes to the session object and leave reading from sessions intact:
# self.session[cnt_key] = str(cnt)
Any help would be much appreciated.
The first argument to get_session is the name, if you want to change from the default. You are passing a response object, which is wrong.
#webapp2.cached_property
def session(self):
return self.session_store.get_session(backend='datastore')
Using the following code, I get the sub sequent crash.
Here is a gist of the full django app: https://gist.github.com/thnee/8e7c6b22f350582efe57
Below are the important parts:
models.py
class Color(models.Model):
name = models.CharField(max_length=255)
class Shirt(models.Model):
name = models.CharField(max_length=255)
colors = models.ManyToManyField(Color)
forms.py
class ShirtForm(forms.ModelForm):
class Meta:
model = Shirt
using the form
def run_form(data):
form = ShirtForm(data)
if form.is_valid():
print 'success'
else:
print dict(form.errors)
# color id is integer (and 1 exists in database)
run_form({'name': 'foo', 'colors': [1,]})
# result: success
# color id is of type string
run_form({'name': 'foo', 'colors': ['asdf',]})
# result: {'colors': [u'"asdf" is not a valid value for a primary key.']}
# color id is of type list
run_form({'name': 'foo', 'colors': [['asdf'],]})
# expected result: {'colors': [u'["asdf"] is not a valid value for a primary key.']}
# actual result: TypeError: int() argument must be a string or a number, not 'list'
# color id is of type dict
run_form({'name': 'foo', 'colors': [{'asdf': 'qwer'},]})
# expected result: {'colors': [u'{"asdf": "qwer"} is not a valid value for a primary key.']}
# actual result: TypeError: int() argument must be a string or a number, not 'dict'
results in the following stack trace
Traceback (most recent call last):
File "/usr/lib/python2.7/wsgiref/handlers.py", line 85, in run
self.result = application(self.environ, self.start_response)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/contrib/staticfiles/handlers.py", line 67, in __call__
return self.application(environ, start_response)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 206, in __call__
response = self.get_response(request)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 194, in get_response
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 112, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/mattiasll01/code/tests/model_multiple_choice_field_check_type/mmcfct/stuff/views.py", line 26, in test
run_form({'name': 'foo', 'colors': [['asdf'],]})
File "/home/mattiasll01/code/tests/model_multiple_choice_field_check_type/mmcfct/stuff/views.py", line 12, in run_form
if form.is_valid():
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/forms/forms.py", line 129, in is_valid
return self.is_bound and not bool(self.errors)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/forms/forms.py", line 121, in errors
self.full_clean()
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/forms/forms.py", line 273, in full_clean
self._clean_fields()
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/forms/forms.py", line 288, in _clean_fields
value = field.clean(value)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/forms/models.py", line 1186, in clean
self.queryset.filter(**{key: pk})
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/db/models/query.py", line 593, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/db/models/query.py", line 611, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1204, in add_q
clause = self._add_q(where_part, used_aliases)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1240, in _add_q
current_negated=current_negated)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1131, in build_filter
clause.add(constraint, AND)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/utils/tree.py", line 104, in add
data = self._prepare_data(data)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/db/models/sql/where.py", line 79, in _prepare_data
value = obj.prepare(lookup_type, value)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/db/models/sql/where.py", line 352, in prepare
return self.field.get_prep_lookup(lookup_type, value)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 369, in get_prep_lookup
return self.get_prep_value(value)
File "/home/mattiasll01/.virtualenvs/test/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 613, in get_prep_value
return int(value)
TypeError: int() argument must be a string or a number, not 'list'
Basically what I think would be better is to not only check for ValueError, but also TypeError here: https://github.com/django/django/blob/master/django/forms/models.py#L1218
I don't see anything weird in the results you get since your function is waiting a string or an int, so when you're passing a dict or a list, it does not make it.
I didn't test it at all but this could give you some ideas:
try:
run_form({'name': 'foo', 'colors': [['asdf'],]})
except TypeError:
# Don't make it crash here but handle errors yourself in form.errors
This was resolved in Django ticket 22808
https://code.djangoproject.com/ticket/22808
I am using Backbone.js + Tastypie + Django and am trying to save a model using patch = true to update the points on a model, like
this.save({
points: newPoints
}, {
patch: true
});
This issues a PUT request as it should with the request payload
points: 105
However, I get a 500 error message
{"error_message": "'bool' object has no attribute 'read'", "traceback": "Traceback (most recent call last):
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/tastypie/resources.py\", line 217, in wrapper
response = callback(request, *args, **kwargs)
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/tastypie/resources.py\", line 468, in dispatch_detail
return self.dispatch('detail', request, **kwargs)
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/tastypie/resources.py\", line 491, in dispatch
response = method(request, **kwargs)
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/tastypie/resources.py\", line 1656, in patch_detail
self.update_in_place(request, bundle, deserialized)
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/tastypie/resources.py\", line 1679, in update_in_place
return self.obj_update(bundle=original_bundle, **kwargs)
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/tastypie/resources.py\", line 2209, in obj_update
bundle = self.full_hydrate(bundle)
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/tastypie/resources.py\", line 909, in full_hydrate
value = field_object.hydrate(bundle)
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/tastypie/fields.py\", line 382, in hydrate
value = make_aware(parse(value))
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/dateutil/parser.py\", line 720, in parse
return DEFAULTPARSER.parse(timestr, **kwargs)
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/dateutil/parser.py\", line 308, in parse
res = self._parse(timestr, **kwargs)
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/dateutil/parser.py\", line 356, in _parse
l = _timelex.split(timestr)
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/dateutil/parser.py\", line 150, in split
return list(cls(s))
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/dateutil/parser.py\", line 147, in next
return self.__next__() # Python 2.x support
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/dateutil/parser.py\", line 141, in __next__
token = self.get_token()
File \"/Users/me/.virtualenvs/project/lib/python2.7/site-packages/dateutil/parser.py\", line 72, in get_token
nextchar = self.instream.read(1)
AttributeError: 'bool' object has no attribute 'read'
"}
Here is my model resource for UserProfile
class UserProfileResource(ModelResource):
"""A resource for the UserProfile model."""
class Meta:
queryset = UserProfile.objects.all()
resource_name = 'userprofile'
authorization = Authorization()
excludes = ['field_to_exclude']
always_return_data = True
Does anyone have tips on how to debug this error?
I had a field which was a datetimefield which was null, and instead of showing up as a a datetime in the api call, is showed up as a boolean. I'm not sure why this happened, but I think this is a bug in tastypie, or I misunderstood something about the configuration, or both.
I excluded this field from the tastypie resource and I was able to PUT and PATCH successfully to the model.