Comments (3)
@arunksoman I'll try to answer your questions in the quickest way, but I surely have to start explaining the design pattern behind the REST extension.
This extension is designed to be used with the whole Emmett stack, including its ORM. The rationale was to design an immediate way to expose standard REST endpoints above a single entity, represented by a Model
. The presentation layer is designed to be handled via serializers and parsers, rather than adding abstraction layers on the entity side. This also because in Emmett models can be used for a lot of things, not just exposing JSON APIs.
Given the upper foreword, I gonna split your questions in 2 groups, as one has a very simple answer, the other 2 implies quite a lot of missing context.
if the json data is not associated with any Model, how can I use this extension?
I think the most robust answer I gan give you is: probably you shouldn't use this extension for that. Plain Emmett would be definitely supportive in working with json data regardless of the source, as you have the @service.json
decorator and the ServicePipe
pipe to mount in your routes.
why it is mandatory to have return data from an endpoint only associated with a Model?
Because Emmett-REST is designed for RESTFul APIs, which means not just fetching json data, but works with entities: creating, updating and deleting them. And the easiest way to design a RESTFul API is having verbs for a single entity, and thus a single Model. Making changes to other entities can still be done, but it is really dependant on your application logic, and providing a common way of doing so would be impossible. Should that be done on the Model level? On the controller level? Somewhere else?
In case you want to present aggregated data coming from multiple entities, then, again, is probably easier to just write a specific get
route where you produce the query and the serialization you need.
How can we create nested json schema with emmett_rest? For example, data from more than one model or data from more than one related Model?
I would say it is really dependant on the type of relation you have between your entities, and what you need to do.
For instance, is it a belongs_to
? Then probably you just want to serialize and deserialize the representation of the related entity, but still work with relations in the module. Which means you probably want to write a custom serializer and a custom parser for that (you can see in the example there's the serialization of a related set of tags
).
Also, since serializers and parsers are classes that can be initialized just passing the model they work on, you can define any number of serializers/parser and re-use them inside your code:
from emmett_rest import Serializer, serialize
class AssigneeSerializer(Serializer):
attributes = ['id', 'email']
class TaskSerializer(Serializer):
_assignee_serializer = AssigneeSerializer(User)
def assignee(self, row):
return serialize([row.assignee], self._assignee_serializer)[0]
For has_many
relations and further, things get a bit more complicated. For sure my tendency would be to created nested REST modules rather than handling all the relations within a single one, so let's say if we have a Task
and many assignees, I would prefer having a REST module working on the join model under /tasks/{task_id}/assignees
instead of making a lot of logic in the Task
module. Something like:
tasks = app.rest_module(__name__, 'api_task', Task, url_prefix='tasks')
class TaskRelatedPipe(Pipe):
async def pipe(self, next_pipe, **kwargs):
request.task = Task.get(kwargs.pop('task_id'))
if not request.task:
response.status = 404
return tasks.error_404()
return await next_pipe(**kwargs)
tasks_related = app.module(__name__, 'api_task_related', url_prefix='tasks/<int:task_id>')
tasks_related.pipeline = [TaskRelatedPipe()]
tasks_assignees = task_related.rest_module(__name__, 'api_task_asignee', User, url_prefix='assignees')
@tasks_assignees.get_dbset
def fetch_assignees():
return request.tasks.assignees
you then probably want to remove the update method and override the create and delete ones to actually work on relations and not users, but you probably got the idea.
Managing relations inside the Task
module would instead require to probably override all the methods to perform the additional operations on the related entities, which can be done as well with decorators or subclassing the basic RESTModule
class, but for sure is more error-prone.
In the end, without additional context, and a clear idea on what you need to do, is quite hard to give you the "perfect answer", but I hope to have exposed all the options on the table here :)
from rest.
Thank you so much for your time. I think I have to read few more times in order understand answer. Can I ask another question? Can we still generate open API docs if we are using @service.json
with the help of this extension?
from rest.
Can we still generate open API docs if we are using
@service.json
with the help of this extension?
Unfortunately not. OpenAPI integration is part of the REST extensions, as it uses models to generate schemas.
It is possible to add custom endpoints to OpenAPI schemas for an existing module, but not for generic routes. That will require to write all the schemas manually, and thus it felt a little pointless to give "an integration".
from rest.
Related Issues (17)
- Congratulations HOT 1
- [openapi] Export api doc to pdf
- [openapi] How do I use contact? HOT 1
- [openapi] Bug in paths using @openapi.include
- [openapi] json error with security_schemes
- About query language HOT 3
- Add support for modules groups
- upgrade requirements.txt HOT 3
- Using cache HOT 2
- Help with Query Language HOT 3
- update_values rules in models HOT 8
- complex query HOT 1
- Integrate swagger HOT 8
- Deprecated notification with emmet 2.1 HOT 2
- Posible bug in parse_params HOT 4
- Update dependence for Emmett 2.2 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rest.