I am trying to figure out how to show all endpoints from an API I've written. In browsing to the root of the API, I see a list of resources and a single get endpoint. How do I generate a list to show all endpoints? I tried django-tastypie-swagger but had the same results. It only listed a few GET methods for each resource and didn't show all the prepend_urls that I added to the resource. Any help is appreciated!
Edit:
I have some helper methods in the get_manufacturer_wedges to help with the response. Side note, I'm very new to python and this whole stack. I come from a c#.net background. I am building a golf app.
class ManufacturerResource(BaseMongoResource):
class Meta:
max_limit = 0
queryset = Manufacturer.objects.all().order_by('id')
allowed_methods = ('get')
resource_name = 'manufacturers'
include_resource_uri = False
def prepend_urls(self):
return [
url(r"^(?P<resource_name>%s)/(?P<pk>[\w\d_.-]+)/wedges/$" % self._meta.resource_name,
self.wrap_view('get_manufacturer_wedges'), name="api_get_manufacturer_wedges"),
]
def get_manufacturer_wedges(self, request, **kwargs):
prim_key = kwargs['pk'] + "|Wedge"
wedges = Club.objects(_id__startswith=prim_key).order_by('name')
return self.create_response(request, HelperMethods.obj_to_list(wedges))
Here is the output when I go to the root of the api (/api/v1/):
{
"file_upload" : {
"schema" : "/api/v1/file_upload/schema/",
"list_endpoint" : "/api/v1/file_upload/"
},
"members" : {
"schema" : "/api/v1/members/schema/",
"list_endpoint" : "/api/v1/members/"
},
"manufacturers" : {
"schema" : "/api/v1/manufacturers/schema/",
"list_endpoint" : "/api/v1/manufacturers/"
},
"courses" : {
"schema" : "/api/v1/courses/schema/",
"list_endpoint" : "/api/v1/courses/"
},
"clubs" : {
"schema" : "/api/v1/clubs/schema/",
"list_endpoint" : "/api/v1/clubs/"
}
}
Related
I am just starting develop with flask-restplus and I am not a native speaker,
but I will try to describe my question as clear as I can.
I know there is a fields module in flask that help us define and filter response data type,
such as String, Integer, List and so on.
Is there any way to allow NULL / None when using fields module?
the following is my code that using field module to catch the value,
add_group = api.model(
"add_group",
{"team_groups": fields.List(fields.Nested(api.model("team_groups", {
"name": fields.String(example="chicago bulls", description="name of add group"),
"display_name": fields.String(example="bulls", description="display name of add group")})))})
and if the data type of display_name is not String, there would be the following error raised,
{
"errors": {
"team_groups.0.display_name": "123 is not of type 'string'"
},
"message": "Input payload validation failed"
}
what I want is when entering display_name, I can enter bulls or None
It seems few of the reference data / questions can be found, and I only found one result related
to my question, but eventually converting as non-null value to solve the issue.
if there is any part of my question not much clear,
please let me know, thank you.
the following is my develop environment:
flask-restplus 0.13.0
Python 3.7.4
postman 7.18.1
The following is my updated code:
from flask_restplus import Namespace, fields
class NullableString(fields.String):
__schema_type__ = ['string', 'null']
__schema_example__ = 'nullable string'
class DeviceGroupDto:
api = Namespace("device/group", description="device groups")
header = api.parser().add_argument("Authorization", location="headers", help="Bearer ")
get_detail_group = api.model(
"getdetail",
{"team_groups": fields.List(fields.String(required=True,
description="team group id to get detail", example=1))})
add_group = api.model(
"add_group",
{"team_groups": fields.List(fields.Nested(api.model("team_groups", {
"name": fields.String(example="chicago bulls", description="name of add group"),
"display_name": NullableString(attribute='a')})))})
if I input the following payload: (by postman)
{
"team_groups": [
{
"name": "chicago bulls",
"display_name": null
}
]
}
It still returns:
{
"errors": {
"team_groups.0.display_name": "None is not of type 'string'"
},
"message": "Input payload validation failed"
}
Yes, you can create a child class and use it instead of default ones, which will accept None as well
class NullableString(fields.String):
__schema_type__ = ['string', 'null']
__schema_example__ = 'nullable string'
So your code will look like
{ "property": NullableString(attribute=value)}
Additionally you can visit the issue github.com/noirbizarre/flask-restplus/issues/179
if some of your fields are optional then make required=False
add_group = api.model(
"add_group",
{"team_groups": fields.List(fields.Nested(api.model("team_groups", {
"name": fields.String(example="chicago bulls", description="name of add group"),
"display_name": fields.String(example="bulls", description="display name of add group", required=False)})))})
Here's slightly evolved approach that I use. It lets you have fields of any type as nullable.
def nullable(fld, *args, **kwargs):
"""Makes any field nullable."""
class NullableField(fld):
"""Nullable wrapper."""
__schema_type__ = [fld.__schema_type__, "null"]
__schema_example__ = f"nullable {fld.__schema_type__}"
return NullableField(*args, **kwargs)
employee = api.model(
"Employee",
{
"office": nullable(fields.String),
"photo_key": nullable(fields.String, required=True),
},
)
Size of data to get: 20,000 approx
Issue: searching Elastic Search indexed data using below command in python
but not getting any results back.
from pyelasticsearch import ElasticSearch
es_repo = ElasticSearch(settings.ES_INDEX_URL)
search_results = es_repo.search(
query, index=advertiser_name, es_from=_from, size=_size)
If I give size less than or equal to 10,000 it works fine but not with 20,000
Please help me find an optimal solution to this.
PS: On digging deeper into ES found this message error:
Result window is too large, from + size must be less than or equal to: [10000] but was [19999]. See the scrolling API for a more efficient way to request large data sets.
for real time use the best solution is to use the search after query . You need only a date field, and another field that uniquely identify a doc - it's enough a _id field or an _uid field.
Try something like this, in my example I would like to extract all the documents that belongs to a single user - in my example the user field has a keyword datatype:
from elasticsearch import Elasticsearch
es = Elasticsearch()
es_index = "your_index_name"
documento = "your_doc_type"
user = "Francesco Totti"
body2 = {
"query": {
"term" : { "user" : user }
}
}
res = es.count(index=es_index, doc_type=documento, body= body2)
size = res['count']
body = { "size": 10,
"query": {
"term" : {
"user" : user
}
},
"sort": [
{"date": "asc"},
{"_uid": "desc"}
]
}
result = es.search(index=es_index, doc_type=documento, body= body)
bookmark = [result['hits']['hits'][-1]['sort'][0], str(result['hits']['hits'][-1]['sort'][1]) ]
body1 = {"size": 10,
"query": {
"term" : {
"user" : user
}
},
"search_after": bookmark,
"sort": [
{"date": "asc"},
{"_uid": "desc"}
]
}
while len(result['hits']['hits']) < size:
res =es.search(index=es_index, doc_type=documento, body= body1)
for el in res['hits']['hits']:
result['hits']['hits'].append( el )
bookmark = [res['hits']['hits'][-1]['sort'][0], str(result['hits']['hits'][-1]['sort'][1]) ]
body1 = {"size": 10,
"query": {
"term" : {
"user" : user
}
},
"search_after": bookmark,
"sort": [
{"date": "asc"},
{"_uid": "desc"}
]
}
Then you will find all the doc appended to the result var
If you would like to use scroll query - doc here:
from elasticsearch import Elasticsearch, helpers
es = Elasticsearch()
es_index = "your_index_name"
documento = "your_doc_type"
user = "Francesco Totti"
body = {
"query": {
"term" : { "user" : user }
}
}
res = helpers.scan(
client = es,
scroll = '2m',
query = body,
index = es_index)
for i in res:
print(i)
Probably its ElasticSearch constraints.
index.max_result_window index setting which defaults to 10,000
I was following the example here: https://github.com/pyeve/eve-demo/blob/master/settings.py
When I go to localhost:5000/apps, I can see all the documents in my collection, but when I search for an email at localhost:5000/apps/example#gmail.com, it says '404 not found'.
I've confirmed the regex, and the email addresses are in the documents. Can anyone see what might be wrong?
run.py
from eve import Eve
if __name__ == '__main__':
app = Eve()
app.run()
settings.py:
RESOURCE_METHODS = ['GET', 'POST', 'DELETE']
ITEM_METHODS = ['GET', 'PATCH', 'PUT', 'DELETE']
MONGO_HOST = 'localhost'
MONGO_PORT = 27017
MONGO_DBNAME = 'test_database'
apps = {
'item_title' : 'app',
'additional_lookup' : {
'url' : 'regex("\b[\w.-]+?#\w+?\.\w+?\b")',
'field' : 'developer_email',
},
'schema': {
'address' : {
'type' : 'string'
},
'developer_email' : {
'type' : 'string',
'minlength' : 1,
'maxlength' : 15,
'required' : True,
'unique' : True,
}
}
DOMAIN = {
'apps' : apps,
}
In your settings.py you aren't doing the lookup correctly. It should be.
apps = {
'item_title' : 'app',
'additional_lookup' : {
'url' : 'apps/regex("\b[\w.-]+?#\w+?\.\w+?\b")',
'field' : 'developer_email',
},
'schema': {
'address' : {
'type' : 'string'
},
'developer_email' : {
'type' : 'string',
'minlength' : 1,
'maxlength' : 15,
'required' : True,
'unique' : True,
}
}
You can't add more than one additional lookup to the same endpoint. What you can do however, is have multiple endpoints consuming the same datasource. By default standard item entry point is defined as /apps/'objectID'/. You will have to configure another endpoint to /apps/'new endpoint'.
Python-Eve: More than one additional lookup
#Vorticity pointed out a fix in a related question. Try the following:
'additional_lookup': {
'url': 'regex("[a-zA-Z0-9_.+-]+#[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")',
'field': 'developer_email'
}
You should be able to retrieve your item with or without url encoding eg:
localhost:5000/apps/example#gmail.com
localhost:5000/apps/example%40gmail.com
If you have any interest in making your items retrievable at the item level by email _only (not object id), you can use item_lookup_field together with item_url:
apps = {
...
'item_url': 'regex("[a-zA-Z0-9_.+-]+#[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")',
'item_lookup_field': 'developer_email'
}
i have a payload as shown below which is stored in mongodb
{
"_id" : ObjectId("5865fbf5558b670ac091c81e"),
"sensors" : [
{
"sensorStatus" : "green ",
"sensorName" : "s1"
},
{
"sensorStatus" : "red ",
"sensorName" : "s2"
}
],
"camera" : [
{
"cameraName" : "cam1",
"cameraStatus" : "live"
},
{
"cameraName" : "cam2",
"cameraStatus" : "live"
}
],
"checkpoints" : [
{
"checkPointName" : "chk1"
}
]
}
trying to write route to display this data as shown below
#gateway_bp.route('/gateway',methods=['GET'])
def list_gateWay():
gateways = Gateway.query.all()
print gateways
return Response(json.dumps(gateways), mimetype='application/json')
i am getting the error has
TypeError: <app.model.canvasmodel.Gateway object at 0x02E99D10> is not JSON serializable
the schema is as shown below
from app.dbconfig.extensions import db
class Sensors(db.Document):
sensorName = db.StringField()
sensorStatus = db.StringField()
class Camera(db.Document):
cameraName = db.StringField()
cameraStatus = db.StringField()
class Checkpoints(db.Document):
checkPointName = db.StringField()
class Gateway(db.Document):
sensors = db.ListField(db.DocumentField(Sensors), db_field='sensors')
camera = db.ListField(db.DocumentField(Camera), db_field='camera')
checkpoints = db.ListField(db.DocumentField(Checkpoints), db_field='checkpoints')
please help to correct the get request thanks
Does anyone know, how I can implement the following MongoDB query using a MongoEngine Raq-Query?
db.getCollection('subscribers').find({
'_id': ObjectId("579e60b0c525fd2037e8dd31"),
'history.content.read_process_msg': {
'$exists':true
},
'history.content.read_processed': {
'$exists':true
},
'history.content.read_processed': false
},
{'history.$':1})
I read, that the raw-query doesn't support projections and that one should use .only() instead. But the problem here is, that it returns all the empty documents also…
Any advice?
Edit: Here are my models and a sample document:
class Subscriber(Document):
service = StringField()
history = EmbeddedDocumentListField('SubscriberHistory')
def __str__(self):
return self.service
class SubscriberHistory(EmbeddedDocument):
action = StringField()
content = DictField()
def __str__(self):
return self.action
And the sample:
{
"_id" : ObjectId("579e60b0c525fd2037e8dd31"),
"service" : "foo",
"history" : [
{
"action" : "outbound",
"content" : {
"read_processed" : false,
"message_data" : {
"text" : "w00t?"
},
"read_process_msg" : {
"$ref" : "bots_messages",
"$id" : ObjectId("57a6529dc525fd8066ee25b3")
}
},
"created_at" : ISODate("2016-08-06T21:12:00.986Z")
}
]
}