-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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
Docs clarifications for "Non-Model ViewSets" #3373
Comments
@ncoghlan thanks for the feedback. The documentation may already have those informations here and there but I think it would benefit having all those grouped together. For example, the routing part is described in the Routers section. We started discussion whether this use cases should go to the API documentation or be part of some sort of blog or collection of use cases. |
Perhaps a Topic for "Custom ViewSets" would be appropriate? I since found more of the docs I needed under Serializers (they cover implementing create/update on the serializer in order to enable the save() method). The "set_password" example in the ViewSet docs then led me to a basic "create" implementation that looks like:
Your mention of the routing API did remind me of an additional bit of reverse engineering I needed to do, which was finding out the names of the generated API endpoints in order to reference them from a template. I ended up using |
@ncoghlan Interesting yup - we do a pretty poor job both of formalizing the browsable API behavior (both in implementation - yuck, and in interface). Could be scope for rounding out this section: http://www.django-rest-framework.org/topics/browsable-api/ |
@ncoghlan create is called after the serializer is validated. We should likely swap the order of the save / validation sections in the serializer documentation. Edit: forget about this comment, I just realised it's the view's update, not the serializer one. |
Sorry, I wasn't clear - that example create() method is the one on the ViewSet, which only receives the request object and still needs to validate the data (unless I've completely misread the validation documentation). |
For the record, the API prototype I'm working on is at https://github.com/ncoghlan/repofunnel/blob/master/copr2pulp/restapi.py While I've used DRF before, that was about 4 years ago, so I'm effectively relearning it from scratch as I go :) |
Another topic that's handled by default in HyperlinkedModelSerializer, but needs to be handled manually in custom Serializers: embedding the URL for an entity in its own representation. Reading through the serializer code suggests there's also some particular details related to the Location header when sending HTTP 201 responses. To get that to work with data dictionaries rather than full objects, I needed the following changes/helpers:
And then setting view_name, lookup_field and lookup_url_kwarg appropriately in the field definition. I was able to figure that out based on a combination of the Model focused docs at http://www.django-rest-framework.org/api-guide/serializers/#how-hyperlinked-views-are-determined, the HyperlinkedIdentityField docs and reading the source code for HyperlinkedIdentityField, and HyperlinkedRelatedField. I think my original intuition that ViewSets would be a good fit for this "local proxy for a remote API" use case is being borne out, there just isn't a clear overview of the additional things you need to take into account when you're working with just ViewSets and Serializers, and no local Model objects. |
This one should be treated as a different issue. It's a bit more than just documentation to me. |
@ncoghlan Noted yup - don't know how we'd want to handle it best, but there's a bunch of coupling there - tends to be soft (ie won't fail if it's not as expected, but will eg degrade the browsable API etc) |
BTW, I've worked a bit on a demo of a model less API for DRF. |
I think @xordoquy is right that the hyperlinking question is more than just docs, so I moved that out to a separate RFE. |
@ncoghlan 👍 thanks ! |
I think we ought to close this off as stale. |
I'm using Django REST Framework for an API integration project (i.e. presenting a unified API that abstracts a subset of the APIs for multiple backend services), and aiming to keep the abstraction layer as stateless as possible.
I think it's excellent for this purpose, but the regular ViewSet examples in the documentation all assume the use of local model objects, and so have required a bit reverse engineering to figure out the key patterns needed to implement my own custom ViewSet classes that work correctly with the rest of the framework (including the browsable API). So far I've figured out that the bare minimum is:
Serializer
subclass, and set that asserializer_class
on the custom ViewSet (this is needed to get the submission forms to appear correctly on the browsable API)Response(self.serializer_class(data, many=True).data)
from list methodsResponse(self.serializer_class(data).data)
from retrieve methodsraw_data = serializers.DictField(read_only=True)
I'm still figuring out the right implementation patterns for create, update, partial update, and destroy...
As far as where this could go in the documentation, it seems to me that the current "Marking extra extractions for routing" section in http://www.django-rest-framework.org/api-guide/viewsets/ could be broken up to have a preceding section on "Integrating with Routers and the Browsable API" that covers the default methods the routers look for, and how the browsable API generates the default forms.
If this seems reasonable, I'd be happy to work on a PR for it.
The text was updated successfully, but these errors were encountered: