artory / drf-hal-json Goto Github PK
View Code? Open in Web Editor NEWApp for Django REST Framework 3 that adds support for `Content-Type: application/hal-json`
License: MIT License
App for Django REST Framework 3 that adds support for `Content-Type: application/hal-json`
License: MIT License
Add a link with templated: true
for the pagination.
See example in https://tools.ietf.org/html/draft-kelly-json-hal-08#section-6
I'm using alanjds/drf-nested-routers to support nested paths like:
/patients/{patient_pk}/events/
When I use a HAL serializer in these nested views, the self
link isn't generated correctly. I'm able to work around the issue by manually defining self
:
self = HalHyperlinkedIdentityField(
view_name='event-detail',
)
Is there a canonical way to be handling this? Do I need to be implementing some specific method? Should this be working "out of the box"?
(relocated from seebass/drf-hal-json#7)
I'm reasonably familiar with DRF and was confused by the loss of the DRF Browsable API when I followed the README example. I wasn't familiar with the setting so I ended up deleting the DEFAULT_RENDERER_CLASSES
entry to "fix" things.
I suggest including BrowsableAPIRenderer
in the README example to replicate stock DRF as closely as possible. Any user who has removed BrowsableAPIRenderer
will know to do the same when presented with your example. However, it won't cause unexpected behavior for users who have not modified the DRF default.
I built a serializer that would accept a full, nested representation for a model and create an instance for that representation. Once the representation existed, it made sense to return a _links
entry for that instance. To do this, I wrapped a Serializer
with a class that (in to_representation
) extracted serialized[LINKS_FIELD_NAME][URL_FIELD_NAME]
and inherited from HalIncludeInLinksMixin
to get it put in links.
Unfortunately, this nested serializer matches both _is_link_field
and _is_embedded_field
. This is a problem because to_representation
uses pop
on link_field_names
so the field is absent by the time embedded_field_names
tries to access it (i.e. KeyError
).
I'm looking for feedback on the situation:
Are asymmetric serializers anti-pattern? Should I have a separate read and write serializer? Or is it even anti-pattern to use asymmetric serializers on a view? For example, the RFC says:
A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.
At least for the sake of argument, I submit that a _links
entry is "equivalent" (they did not say "identical") to the original, embedded resource.
If an asymmetric serializer like this is reasonable, we could improve _is_embedded_field
, is_link_field
, and is_link_contribution_field
to ensure a field never matches more than one.
Other suggestions?
In #64, I created test cases to illustrate the problem. Long story short, I believe it should be possible to PUT the body of a GET to the same endpoint in the default case. This does not work because drf-hal-json
returns a JSON object but (seems to) expect stringified JSON.
To avoid getting the API Browser pages, I used the format
query parameter in DRF (e.g. http://localhost:8085/api/tasks/4/?format=json
). While it looks like including query parameters can be valid, the format
parameter does not uniquely identify the resource. I do not therefore believe it should be included.
Because other query parameters are allowed, we probably ought to exclude this one explicitly. I realize the issue is minor, but I think it's more important that HAL actually comply with the associated specification than (say) DRF.
"_links": {
"self": {
"href": "http://localhost:8000/api/v1/customers"
},
"next": {
"href": null
},
"previous": {
"href": null
}
}
It would make more sense to leave out the next
and previous
relations entirely, if there are no links.
You can't unpack like this before Python 3.5
resp = {**resp, **ret}
https://github.com/Artory/drf-hal-json/blob/master/drf_hal_json/serializers.py#L43
However your readme and setup do not specify a dependency on Python 3.5
It think it would be wise to not introduce such a strong requirement (especially for those, like us, who are deploying on AWS Elastic Beanstalk, that provides only a 3.4.3 environnement).
PR is opened.
Currently:
{
"_links": {
"some_relation": {"href": null}
}
}
Should maybe be:
{
"_links": {
"some_relation": null
}
}
or dropped altogether.
SlugRelatedField
is getting put into the _links
section even if it's not a URI (let alone a valid one).
I'm using the SlugRelatedField
to extract the name of a Django group. I need the group name to tell a user who's responsible for a task (if that user is not). The groups are not available over REST so it doesn't make sense to represent them as a linkable resource. As far as REST is concerned, the slug is just an attribute of the object.
While SlugRelatedField
could be used to pick a URI off an object, this behavior is not the appropriate default. Instead, I believe this feature should require a dedicated class asserting that it's representing a UriSlugRelatedField
.
My workaround for #18 was to manually declare the self
field on the serializer:
self = HalHyperlinkedIdentityField(
view_name='event-detail',
)
I also wanted to display only that field so I set fields = ['self']
. Out of curiosity, I tried limiting another serializer to just self
and got an error that it was not declared on the serializer.
Is there always a better way to get a link-only representation so fields = ['self']
is anti-pattern? Or is this a reasonable thing to do in some circumstance that the HalModelSerializer
should explicitly declare this field (technically URL_FIELD_NAME
) so it can be included in fields
?
FWIW due to error checking code, the HalModelSerializer
would also need a Meta.fields
that includes this value.
FYI. A common way to find an active version of a library is to look at the "fork" tree. This package isn't attached so even I sometimes have trouble finding it. I imagine you detached it intentionally, but I'd like to at least draw attention to one big disadvantage.
As this fork most likely won't be merged back, we should consider asking Github to remove the fork linking and we should possibly also rename the project so that there are no two drf-hal-json
.
Ideas for names? @jstaffans @jakubartory?
I'm trying to conditionally display a HalContributeToLinkField
. I tried returning None
from the getter on the serializer figuring that None
might be suppressed. Instead it was displayed and set to null
.
I don't think creating a null
is the right behavior here because it makes HAL-invalid JSON (if I understand HAL correctly). I'm not necessarily arguing that it should be suppressed (thought it would have been convenient). For example, it'd be reasonable to throw an error instead.
While working on #20, I had to figure out the appropriate rel name (i.e. key) for a collection. This package hard-codes the word items
in several locations (e.g. here). This is reasonably consistent with DRF's hard coding of "results". However, I'd like to express a series of opinions in increasing degrees of complexity:
I stumbled on a case for calling it item
instead of items
. While the thread acknowledges that the spec is indeterminate and the spec's examples actually deviate, I think the OP is right to argue for non-plural names for collections of single items and plural names for links to collections endpoints themselves.
I don't think we should hard code the name inline. _links
and _embedded
are both defined by the specification (i.e. immutable) and the package still uses centralized "constants".
At minimum, I think we should permit a package-level configuration.
Even better, I think this should be configurable using a serializer-level Meta
configuration.
I see a case for generating the name dynamically. While the list is a list of abstract items, it's really a named relation. The relation is not to an abstract items but to a specific type of item. It may be the case that pure-HAL should be able to deduce the type from that rel name.
While this is not a critical issue, it would produce a breaking change in the future so this is an especially good opportunity to make a change if any of the above were persuasive.
I tried the current version of master on a py2.7 project and had issues with the empty super calls. I'll put together a PR, but want to draw attention to the issue to help avoid additional instances from being introduced in active branches.
Has anyone else run into a use case for a field (like HyperlinkRelatedField
) that uses query params to return (only) the related items?
As a toy example, consider a list of Projects and their related Tasks. For a variety of reasons, I've been getting a list of Project Tasks through an endpoint like /projects/#/tasks
. A Project's _links
will include this URI. When accessed, each embedded item's self
points to /tasks/#/
so the singletons have only one proper URI. This has worked out great because I can populate a HyperlinkedRelatedField
using drf-nested-routers
and a syntax like:
tasks = HalHyperlinkedRelatedField(
view_name='project-task-list',
read_only=True,
lookup_url_kwarg='project_pk',
source='pk'
)
I recently ran into a situation where it would have been more convenient to link the tasks using a URI like /tasks/?project=#
. From what I've read, a URI is opaque so there's no HATEOAS reason to prefer one to the other. In fact, the query params approach may be simpler in more complicated subsets like "incomplete tasks" (/projects/#/tasks?status=incomplete
is equivalent but requires support for two kinds of filtering).
I can set up DRF's filters to support this URI, but there doesn't appear to be an existing serializer field to build a URI like this. I've worked around the issue in my specific case, but am curious if anyone else has had use of a field like this (or is aware of a better, general-purpose solution).
Consider a collection URL like:
/parents/{id}/childs
In a HATEOAS world, it makes sense (to me anyway) for this collection to include a _links
entry to navigate back to its parent. Since the link should be accessible even if the collection is empty, it would need to be included in the collection's _links
(vs. singleton _links
). I don't believe there's anything in DRF that is comparable. The closest are the links in Pagination
but they're hard-coded into the Pagination
class (i.e. not customizable on a per-type basis).
I contributed a HalListSerializer
to this project. It seems to me that the HalListSerializer
is the "right" to do this because a custom ListSerializer
can be nested inside each (singleton) Serializer
(even though uses rarely do). The default implementation of ListSerializer
does not support serializer fields on the ListSerializer
, but I could adapt our local implementation to make it possible.
Please note that Pagination
classes already conflict/compete with the ListSerializer
for creating a top-level representation. It may be necessary (even advisable) to rewrite the Hal
pagination classes to just add/inject _links
entries into the HalListSerializer
(which already nests the serializer's response under _embedded['items']
).
Thoughts?
SlugRelatedField is never a http link, so it might not be useful to end up there.
I have a custom Serializer that is not a ModelSerializer. I need to incorporate HAL formatting (e.g. to_representation
, but don't want/need the ModelSerializer
dependendencies (which are not compatible).
It's been ages since I was in this code. Does anyone know if there are hard(ish) ModelSerializer
dependencies? Or if this was just a quirk of original use case?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.