-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HAL List Serializer #20
Conversation
drf_hal_json/serializers.py
Outdated
@@ -1,14 +1,51 @@ | |||
from collections import defaultdict | |||
|
|||
import rest_framework |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'rest_framework' imported but unused
Sorry. Had a face-palm moment when I realized that |
Thanks for this! We implemented lists of links a while ago, but skipped over embedding them, in order to not blow up JSON responses too much for the default case. That's why there is a test serializer which uses It would be interesting to hear if this PR somehow changes that, or if it's only about list-type fields that are part of a resource and not "related" to it. A few test cases would help very much for understanding this PR! |
The current state of this PR only affects the top-level representation of a collection endpoint (e.g. Here's the outline of the "conceptual" test case that fails in the current codebase:
I actually discovered the issue by looking at examples of HAL-compliant top-level collections (exemplified by this SO answer). Even for an un-paged collection, they indicate a barebones format like:
Obviously, this structure includes a |
I'll try to find time to add test cases as well. The test harness is... less unittest than I'm used... to so there's a non-trivial learning curve there too. |
Yeah, the test harness is one of the things that is still implemented as it was in the original repo. We'll try to clean it up when time permits.. To your ListSerializer issue: what if you just use HalModelSerializer? If you run the "abundant resources" test case, the response is rendered along the lines of HAL:
Does this solve your issue? |
I don't think so. In DRF:
Because your test case includes "next", I'm pretty sure it's an example of (2). My PR is intended to address (3). FWIW I dislike that DRF behaves this way. I think it's confusing that adding pagination requires a rewrite of the UI, but I've reported far more serious violations of REST semantics that are still unresolved. I know better than to tilt with that DRF windmill, but this package should definitely conform to spec. edit: if prev/next links are placed in headers (not the default), the body of a paginated DRF response may be rendered as a list as well |
Gotcha, I agree that the response should always be a dict. If you take a look at the test case again, though, the first assertion is for a resource that is not paginated (no prev or next links). This also renders as a dict. I could however reproduce your issue by turning off pagination for the test project completely, in |
Yes. I think "no pages" is testing the case where all of the items fit on one page. The resource is still paginated (technically speaking) but no links are rendered. The |
c10c20e
to
5023139
Compare
Test case added. |
- adapt HalModelSerializer to use HalListSerializer
…entation`) - use correct context object (`context` not `_context`)
- `HalRelatedModelSerializer` to correctly render related fields (i.e. without `embedded`) - fix test harness to use `HalRelatedModelSerializer`
…de different structures to root (`data`) and nested (`to_representation`) uses
…ols.ietf.org/html/draft-kelly-json-hal-08#section-6 (but uses `items` to match pagination package)
5023139
to
fd45e70
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late approval, great work!
drf_hal_json/serializers.py
Outdated
{ | ||
LINKS_FIELD_NAME: { | ||
URL_FIELD_NAME: { | ||
'href': self.build_view_url() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or should I be using (e.g. here):
{'href': self.request.build_absolute_uri()}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to build URI:s the same way everywhere, so I would go with self.request.build_absolute_uri()
, if that is enough for your use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It certainly looks like it should work (and eliminates the need for some extra code). At some point, we're going to need to update that code to address #27 but it's not urgent/blocker. I'll push the change.
This PR adds HAL-compliant list serialization to HalModelSerializers:
HalListSerializer
(inherits fromListSerializer
) to generate HAL-compliant output..data
to avoid poisoning list of related objectsHalModelSerializer
to useHalListSerializer
by default (__new__
callsmany_init
so the change is found here)This PR is not as clean as I'd like:
BaseSerializer.many_init
so I had to conditionally inject the new default inMeta.list_serializer_class
.default_list_serializer
logic (or something similar) would be pushed up to DRF's BaseSerializer so we could just set a new default in this class.HalListSerializer.build_view_url
parrots the approach found in DRF (smeared over a bunch of helper functions)Meta
attribute (i.e.base_name
) to support manual overridebase_name
(or something similar) since it would support both-list
and-detail
.I'm not going to actually suggest anything to DRF until the collaborators here are satisfied with the approach.
EDIT: Updated to reflect latest code.