Code Monkey home page Code Monkey logo

Comments (5)

swistakm avatar swistakm commented on May 11, 2024

It looks that option 1. is as simple as:

index 25728e3..6368521 100644
--- a/src/graceful/serializers.py
+++ b/src/graceful/serializers.py
@@ -64,7 +64,7 @@ class MetaSerializer(type):
         )


-class BaseSerializer(metaclass=MetaSerializer):
+class BaseSerializer(BaseField, metaclass=MetaSerializer):
     """Base serializer class for describing internal object serialization.

     Example:
@@ -81,6 +81,8 @@ class BaseSerializer(metaclass=MetaSerializer):
             height = FloatField("cat height in cm")

     """
+    def __init__(self, details=None, **kwargs):
+        super().__init__(details=details, **kwargs)

     @property
     def fields(self):

Here is a small snippet of code that shows how nested resource serializers could be defined and proofs that it works:

from pprint import pprint

from graceful.serializers import BaseSerializer
from graceful.fields import StringField


class Inner(BaseSerializer):
    fooX = StringField("Foo field", source='foo')
    barX = StringField("Bar field", source='bar')


class Outer(BaseSerializer):
    innerX = Inner(details="inner object", source='inner')
    nameX = StringField("Name field", source='name')


def main():
    outer = Outer()

    internal = {
        "inner": {
            "foo": "something",
            "bar": "something else",
        },
        "name": "my outer"
    }

    print("\n ====== internal ======")
    pprint(internal)

    print("\n === representation ===")
    pprint(outer.to_representation(internal))

    print("\n ====== internal ======")
    pprint(outer.from_representation(outer.to_representation(internal)))

if __name__ == "__main__":
    main()

And example output:

$ python nested.py 

 ====== internal ======
{'inner': {'bar': 'something else', 'foo': 'something'}, 'name': 'my outer'}

 === representation ===
{'innerX': {'barX': 'something else', 'fooX': 'something'}, 'nameX': 'my outer'}

 ====== internal ======
{'inner': {'bar': 'something else', 'foo': 'something'}, 'name': 'my outer'}

But the problem is in how we will handle "describe()" methods in serializers. If they are fields now we should make them described the same way as fields so with "details", "type", "label", "spec", "read_only" attributes. Right now we put all definition to "fields" dictionary of resource metadata dict but we cannot handle this that way anymore.

I think we could utilise serializer class docstring as a field details and completely change the overall layout of description output. Instead of having single fields dict in the resource metadata we could have something more nested:

{
    ...,
    'representation': {  # => result of serializer.describe()
         'details': ... # => serializers docstring
         'label': ...    # => optional label for consistency
         'spec': ...    # => spec, here developer can add link for docs in case of nested serializers
         'type': 'representation', # => optionally 'object'/'dict' to inform it is another dict
         'fields': {  # => content of former 'fields' dictionary
             { # example of single field like str, int, float etc.
                  'details': ...
                  'label': ...
                  'spec': ...
                  'type': ....
                  # => in case of simple fields there is no 'fields' key
              },
              { # example of field coming from different serializer
                  'details': ...
                  'label': ...
                  'spec': ...
                  'type': 'representation'
                  'fields': {...}  # => fields that are serializers will have the same description
              },
         },
    },
}

Alternative way of handling nested descriptions is utilisation of spec field attribute that will now
come really handy. We could assume that resource description structure stays as it is (flat fields dict) and whenever we include serializer as a field the user should supply spec with the link of nested resource documentation. Because resources are self-descriptive (full metadata on OPTIONS request) this can be simply a link to URI of separate nested resource endpoint.

Pros:

  • if user would like to create mutually nested resources (it is possible) we will not end up with infinite description loop
  • it makes possible auto documenters simpler beach they will not need to deal with nested fields descriptions
  • it does not require backwards incompatible changes

Cons:

  • it will be harder to describe nested resources that do not have their own query endpoints

For the problem with describing nested resources that do not have their now API there is a simple solution. One could create virtual endpoint that serves only documentation purpose. It would accept only OPTIONS requests to serve specification but would not deliver any of other manipulation methods (GET/POST/PUT/DELETE).

Also the main reason for having nested resource capabilities is a use case when serializer that is nested is actually reused in some other existing resource endpoint.

from graceful.

swistakm avatar swistakm commented on May 11, 2024

Seems like with the new validation in 1.0.0 version it will be even simpler and more clear. Other problem that have surfaced is how to present validation issues in nested representations and representations that have fields with many=True enables. We need to came up with some new format for validation issues that.

from graceful.

holic-cl avatar holic-cl commented on May 11, 2024

Hi, i am trying to do a nested serialization. My project is using peewee as orm, i am trying to fetch a list of awards with a nested user on the results set.

class AwardListSerializer(BaseSerializer):
    redeemed_at = IntField("Date when the award was redeemed.")
    user = UserSerializer()

This code is not working, my response is returning this:

{
  "meta": {
    "params": {
      "indent": 0,
      "page_size": 10,
      "page": 0
    },
    "length": 1,
    "total_items": 1,
    "page_size": 10,
    "page": 0,
    "prev": null,
    "next": "page=1&page_size=10"
  },
  "content": [
    {
      "redeemed_at": null
    }
  ]
}

I don't know if i am doing something wrong or what. I saw the test with the example to achieve it, but i can't use details neither source params on the constructor of my nested serializer.

Any clue or help i'll be very grateful.

Regards

from graceful.

swistakm avatar swistakm commented on May 11, 2024

@holic-cl, there is little hiatus in this projects. As far as I remember, the proposed change was never included and released. It's mostly because I had no idea how to approach the problem of nested resource descriptions returned from .describe() handler.

Still, this feature is mostly complete so if we agree on some format, I could apply the patch, modify the handlers and release such feature as part of 1.x version.

from graceful.

holic-cl avatar holic-cl commented on May 11, 2024

Oh, ok, thanks for answer.

from graceful.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.