Skip to content

Conversation

@jacobstoehr
Copy link

If pulled, this would extend serpy with the ability to accept a Meta class inside the custom serializer class.
The syntax for this class is heavily borrowed from DRF's ModelSerializer, e.g. it needs a model (either Django or SQLAlchemy) and an exclude or fields attribute which tell serpy which fields to exclude or include in the serialization.

This was inspired by the need to serialize a very big Django model but with greater speed than what DRF provides. However, this had the drawback of also needing to specifiy each field to be serialized in the Serializer, instead of just inserting a Meta class and be done.

I have done some basic benchmarks, this does not negatively impact the standard serialization speed, because of the top level if meta: statement, which will just skip the code if no Meta class is provided. If the class has been provided, the serialization speed doesn't suffer, at least on my machine. I have not conducted any kind of statistical benchmarking, just quick tests using the UNIX time utility.

I wanted to keep this code inside the SerializerMeta, so that the implicit fields are calculated at startup time, not at serialization time. This however means all serializers inheriting from serpy.Serializer will have this ability, not like DRF where only serializers inheriting from rest_framework.serializers.ModelSerializer will have this ability.

This was achieved by adding a check if there is a `Meta` class present inside
the custom serializer.
Now, if that class exists, an attempt is made to get the model information for
both Django models as well as SQLAlchemy models. Others are not supported and
will raise a RuntimeError.
The `_field_map` is then updated accordingly, but MethodFields or custom `attr`
keyword arguments are not overwritten.
This makes it possible to not serialize certain fields.
By adding a `fields` parameter which can be either '__all__' or a list of fields
from the model.
And by making this `fields` attribute or the `exclude` attribute usable, but not
both at the same time.
Before, the `direct_fields` dict holding all fields declared in the custom
serializer was overwritten with all implicitly defined fields from the `Meta`
class inside the custom serializer.

That means if someone declared anything other than a standard Field for an
attribute of the model, this would have been overwritten with a standard Field
instance instead of keeping the explicitly declared field type, effectively
nullifying the effect of the explicit declaration.

Now, if someone was to declare a field explicitly, the SerializerMeta class
will not overwrite this field  with a standard Field instance in the
`direct_fields` dict, but will instead skip this field, thus preserving the
explicit declaration.

Also add some more comments explaining this in the code.
@coveralls
Copy link

Coverage Status

Coverage decreased (-18.0%) to 82.0% when pulling f0e578b on jacobstoehr:master into 0c58fb8 on clarkduvall:master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants