On Monday 05 June 2017 04:14:01 Alison P wrote:
> If I use the default session serializer, I get the following error:
> TypeError at /login/
>
> <class 'OneTimePasswordBackend'> is not JSON serializable
I'm using this is a general solution. Feel free to strike what you don't need.
The basics is that a JSONEncoder knows primitives and how to recurse
containers. The rest is
passed to a method "default", which generates the above error message.
Subclasses should
override it to implement their own knowledge about objects to serialize.
*class JSONModelEncoder(*DjangoJSONEncoder*): *exclude_callback *= None
*recurse_foreign_keys *= True
def get_excluded_fields(*self, instance*): if *self.exclude_callback
*is not None:
return *self.exclude_callback*(*instance*) else: return *[]
*def recurse_foreign(*self, instance, field*) *-> */dict/**: *retval
*= {} if
/isinstance/(*field, models.OneToOneField*): */# OneToOneField is a
subclass of
ForeignKey, thus must be placed # before ForeignKey. # If
parent_link is true, then
we need to pull in the fields # as if they were part of the current
model. /*if not
*field.parent_link*: *parent_obj *= /getattr/(*instance,
field.name*) if
*parent_obj *is not None: *value *= *self.model_to_dict*(
*parent_obj,
exclude*=*self.get_excluded_fields*(*parent_obj*) )
*retval.update*(*value*) elif /isinstance/(*field, models.ForeignKey*):
*/# Resolve
the model pointed to. /foreign *= /getattr/(*instance, field.name*)
if *foreign *is
not None: *value *= *self.model_to_dict*(*foreign*)
*retval[field.name] *=
*value *else: *retval[field.name] *= None elif
/isinstance/(*field,
models.ManyToManyField*): */# Create a list of model dicts.
/modlist *= *[]
related *= /getattr/(*instance, field.name*) for *rel *in *related*:
*modlist.append*(*self.model_to_dict*(*rel*))
*retval[field.name] *= *modlist *else: raise
/TypeError/('recurse_foreign
called on {}'*.format*(/type/(*field*)))
return *retval
*def link_foreign(*self, instance, field*) *-> */dict/**: if
/isinstance/(*field,
models.ManyToManyField*): return *self.recurse_foreign*(*instance,
field*) elif
/isinstance/(*field, models.OneToOneField*): if not
*field.parent_link*: return
*self.recurse_foreign*(*instance, field*) elif /isinstance/(*field,
models.ForeignKey*):
*foreign *= /getattr/(*instance, field.name*) */# raise
ValueError(repr(foreign)) /*if
*foreign *is not None: if /getattr/(*foreign, *'absolute_url'*,
*False): return {
*field.name*: { 'text': *force_text*(*foreign*)*,
*'link':
*foreign.absolute_url, *} }
else: return {
*field.name*: { 'text': *force_text*(*foreign*)*,
*'pk':
*foreign.pk *} }
return {}
def model_to_dict(*self, instance, exclude*=None*, ****kwargs*) *->
*/dict/**:
*"""Convert a model instance to a dictionary of field names and values.
If the model has a method of the same name, that method is called for
three reasons:
#. Centralization. This method can be used in other parts of django
or an application to
provide a consistent dictionary of the model. #. The
default implementation only
maps fields. If the model has important attributes that are
implemented as properties
this mixin will not find them. #. Hiding of sensitive
fields. The model is better
equipped to evaluate if a field contains sensitive information.
/:param/ instance: the model instance to convert /:type/
instance: models.Model
/:param/ exclude: list of fields to exclude from being sent /:type/
exclude: list """
exclude *= *exclude *or *self.get_excluded_fields*(*instance*) if
/hasattr/(*instance,
*'model_to_dict') and *\ */callable/**(/getattr/(*instance,
*'model_to_dict')):
return *instance.model_to_dict*(*exclude, ****kwargs*) *retval *= {}
for *field *in
*instance._meta.fields*: if *field.name *in *exclude*:
continue if
/isinstance/(*field, *(*models.ForeignKey, models.ManyToManyField*)):
if
*self.recurse_foreign_keys*:
*retval.update*(*self.recurse_foreign*(*instance,
field*)) else: *merge *=
*self.link_foreign*(*instance, field*) if
*merge*: *retval.update*(*merge*) else:
*retval[field.name] *=
/getattr/(*instance, field.name*)
return *retval
*def default(*self, obj*) *-> */object/**: *"""Prepares a value for
json representation.
Complex types that are not containers should be handled by this method.
/:param/ obj:
/:type/ obj: object """ *if /isinstance/(*obj,
models.query.QuerySet*): return
/list/(*obj*) elif /hasattr/(*obj, *'model_to_dict') and *\
*/callable/**(/getattr/(*obj,
*'model_to_dict')): return
*obj.model_to_dict*(*exclude*=*self.get_excluded_fields*(*obj*)) elif
/isinstance/(*obj,
models.Model*): return *self.model_to_dict*(*obj*) else:
return
/super/()*.default*(*obj*)
*
--
Melvyn Sopacua
--
You received this message because you are subscribed to the Google Groups
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-users/2490212.PBjjLfRLnk%40devstation.
For more options, visit https://groups.google.com/d/optout.