Code Monkey home page Code Monkey logo

flask-restplus's Introduction

Flask RestPlus

Build status

Code coverage

Documentation status

License

Supported Python versions

Join the chat at https://gitter.im/noirbizarre/flask-restplus

IMPORTANT NOTICE:

This project has been forked to Flask-RESTX and will be maintained by by the python-restx organization. Flask-RESTPlus should be considered unmaintained.

The community has decided to fork the project due to lack of response from the original author @noirbizarre. We have been discussing this eventuality for almost a year.

Things evolved a bit since that discussion and a few of us have been granted maintainers access to the github project, but only the original author has access rights on the PyPi project. As such, we been unable to make any actual releases. To prevent this project from dying out, we have forked it to continue development and to support our users.

Flask-RESTPlus is an extension for Flask that adds support for quickly building REST APIs. Flask-RESTPlus encourages best practices with minimal setup. If you are familiar with Flask, Flask-RESTPlus should be easy to pick up. It provides a coherent collection of decorators and tools to describe your API and expose its documentation properly using Swagger.

Compatibility

Flask-RestPlus requires Python 2.7 or 3.4+.

Installation

You can install Flask-Restplus with pip:

$ pip install flask-restplus

or with easy_install:

$ easy_install flask-restplus

Quick start

With Flask-Restplus, you only import the api instance to route and document your endpoints.

from flask import Flask
from flask_restplus import Api, Resource, fields

app = Flask(__name__)
api = Api(app, version='1.0', title='TodoMVC API',
    description='A simple TodoMVC API',
)

ns = api.namespace('todos', description='TODO operations')

todo = api.model('Todo', {
    'id': fields.Integer(readOnly=True, description='The task unique identifier'),
    'task': fields.String(required=True, description='The task details')
})


class TodoDAO(object):
    def __init__(self):
        self.counter = 0
        self.todos = []

    def get(self, id):
        for todo in self.todos:
            if todo['id'] == id:
                return todo
        api.abort(404, "Todo {} doesn't exist".format(id))

    def create(self, data):
        todo = data
        todo['id'] = self.counter = self.counter + 1
        self.todos.append(todo)
        return todo

    def update(self, id, data):
        todo = self.get(id)
        todo.update(data)
        return todo

    def delete(self, id):
        todo = self.get(id)
        self.todos.remove(todo)


DAO = TodoDAO()
DAO.create({'task': 'Build an API'})
DAO.create({'task': '?????'})
DAO.create({'task': 'profit!'})


@ns.route('/')
class TodoList(Resource):
    '''Shows a list of all todos, and lets you POST to add new tasks'''
    @ns.doc('list_todos')
    @ns.marshal_list_with(todo)
    def get(self):
        '''List all tasks'''
        return DAO.todos

    @ns.doc('create_todo')
    @ns.expect(todo)
    @ns.marshal_with(todo, code=201)
    def post(self):
        '''Create a new task'''
        return DAO.create(api.payload), 201


@ns.route('/<int:id>')
@ns.response(404, 'Todo not found')
@ns.param('id', 'The task identifier')
class Todo(Resource):
    '''Show a single todo item and lets you delete them'''
    @ns.doc('get_todo')
    @ns.marshal_with(todo)
    def get(self, id):
        '''Fetch a given resource'''
        return DAO.get(id)

    @ns.doc('delete_todo')
    @ns.response(204, 'Todo deleted')
    def delete(self, id):
        '''Delete a task given its identifier'''
        DAO.delete(id)
        return '', 204

    @ns.expect(todo)
    @ns.marshal_with(todo)
    def put(self, id):
        '''Update a task given its identifier'''
        return DAO.update(id, api.payload)


if __name__ == '__main__':
    app.run(debug=True)

Contributors

Flask-RESTPlus is brought to you by @noirbizarre. Since early 2019 @SteadBytes, @a-luna, @j5awry, @ziirish volunteered to help @noirbizarre keep the project up and running. Of course everyone is welcome to contribute and we will be happy to review your PR's or answer to your issues.

Documentation

The documentation is hosted on Read the Docs

Contribution

Want to contribute! That's awesome! Check out CONTRIBUTING.rst!

flask-restplus's People

Contributors

a-luna avatar ajmaradiaga avatar avilaton avatar awiddersheim avatar bodgit avatar calvin620707 avatar chuckhend avatar dmvass avatar edgyedgemond avatar fixedd avatar frol avatar j5awry avatar kamforka avatar kvudata avatar leiserfg avatar lrebscher avatar mattflahertypgs avatar mdesetty avatar narfman0 avatar nicolashug avatar nlohmann avatar noirbizarre avatar r0hitsharma avatar rob-smallshire avatar steadbytes avatar tgoodyear avatar tnt-dev avatar tzabal avatar ufian avatar ziirish avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flask-restplus's Issues

No way to set base endpoint?

Hello! I'm trying to set the base endpoint using what the docs says here (parameter endpoint):

:param endpoint: The API base endpoint (default to 'api).

But I'm getting an error, for this parameter seems not used anymore:

def __init__(self, app=None, version='1.0', title=None, description=None,
terms_url=None, license=None, license_url=None,
contact=None, contact_url=None, contact_email=None,
authorizations=None, security=None, ui=True, default_id=default_id,
default='default', default_label='Default namespace', **kwargs):

Tried using the default parameter, but seems to have no effect...

Remove support for model as class

Models as classes are always replacable by classic model definitions.
They are more limited, redundant and too verbose.

I plan te remove them soon. If someone use them, please say it soon !!!

Custom Header documention

Currently I do not see any way to say that custom headers are required ( for api keys and such)

maybe something like
@doc(headers={'API_KEY':'your api key'})

Swagger-ui does not handle properly json arguments

I am building an api where a PUT operation should accept a json object with some well-defined properties. As far as I understood from the flask-restful documentation you can do something like

node_put_parser = api.parser()
node_put_parser.add_argument(
    'timestamp',
    type=int, required=True, help='The time statistics were generated',
    location='json')
node_put_parser.add_argument(
    'interfaces',
    type=dict, required=True,
    help='Statistics per interface, indexed by the ip of the interface',
    location='json')
node_put_parser.add_argument(
    'babel_dump',
    type=str, required=True,
    help='The state of the babeld daemon as generated by the service itself',
    location='json')

The RequestParser seems to work OK (I didn't testing extensively though) but the swagger-ui generates an obscure form that is unusable.

flask-restplus-json-post

Trying to use this form is impossible. For all json parameters, it just gets the latest and use this as the request body.

The firefox debug interface reports the following if I press Try it out

PUT http://localhost:5000/api/map/node/1/statistics

Headers:

Host: localhost:5000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: application/json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json; charset=UTF-8
Referer: http://localhost:5000/api/
Content-Length: 23
Cookie: __utma=111872281.398094953.1364220452.1364220452.1364220452.1; ui_language=en_US; splunkweb_csrf_token_8000=13650718194689432226; session=eyJfaWQiOnsiIGIiOiJObVkwWVRoak5qRTJZalk1WWpjek1qRTBNR0ppTlRRME9XUXdPR1ZqTnpjPSJ9fQ.B4cVLQ.uXmbw59ggilVLP_pxy5dKS-PqOo
Connection: keep-alive

Request Body:

{'127.0.0.1': [1,2,3] }

Is this a swagger-ui limitation or an issue of flask-restplus?

Support for python 2.6 is needed

It turns out that I need python 2.6 support for the project I'm working on. It seems that not too many changes are needed for this, so I will create a pull request shortly.

Full Example & POST method (POST todos) doesn't work through swagger UI

Hi,

http://flask-restplus.readthedocs.org/en/latest/example.html
request URL
http://127.0.0.1:5000/todos/?task=eee

response:
{
"message": "Bad Request",
"status": 400
}

however if I call the same request with
httpie

D:\Projects\sbtools\development\api>http POST http://localhost:5000/todos/?task=www
HTTP/1.0 201 CREATED
Content-Length: 22
Content-Type: application/json
Date: Thu, 13 Nov 2014 03:46:07 GMT
Server: Werkzeug/0.9.6 Python/2.7.5

{
"task": "www"
}

everything worked.

Any ideas?

@ns.route('/')
class TodoList(Resource):
'''Shows a list of all todos, and lets you POST to add new tasks'''
#@api.marshal_with(todo_fields, as_list=True)
def get(self):
'''List all todos'''
return TODOS

@api.doc(parser=parser)
@api.marshal_with(todo_fields)
def post(self):
    '''Ceate a todo'''
    args = parser.parse_args()
    todo_id = 'todo%d' % (len(TODOS) + 1)
    TODOS[todo_id] = {'task': args['task']}
    return TODOS[todo_id], 201

RequestParse.copy() stopped working with flask-restful 0.3.3

After upgrading flask-restful to 0.3.3 the .copy() stop working with the following error:

 File "/home/sque/tmp/flask-restplus/tests/test_reqparse.py", line 46, in test_copy
    cloned = parser.copy()
  File "/home/sque/tmp/flask-restplus/env/local/lib/python2.7/site-packages/flask_restful/reqparse.py", line 312, in copy
    parser_copy = self.__class__(self.argument_class, self.namespace_class)
TypeError: __init__() takes at most 2 arguments (3 given)

Server is returning 404 for swagger assets.

My API runs at the /api path.

api_blueprint = Blueprint("api", __name__, url_prefix="/api")
api = Api(api_blueprint, ui=True)

When I go to /api, I see the following logs:

INFO     2015-03-02 17:31:52,048 module.py:718] default: "GET /api/ HTTP/1.1" 200 3380
INFO     2015-03-02 17:31:52,171 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/jquery-1.8.0.min.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,175 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/css/reset.css HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,179 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/shred.bundle.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,181 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/jquery.slideto.min.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,181 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/css/screen.css HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,182 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/jquery.ba-bbq.min.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,182 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/jquery.wiggle.min.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,182 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/handlebars-2.0.0.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,183 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/underscore-min.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,195 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/highlight.7.3.pack.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,197 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/swagger-ui.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,197 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/backbone-min.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,197 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/swagger-client.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,198 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/marked.js HTTP/1.1" 404 -
INFO     2015-03-02 17:31:52,202 module.py:718] default: "GET /swaggerui/bower/swagger-ui/dist/lib/swagger-oauth.js HTTP/1.1" 404 -

It looks like the static file urls don't include the blueprint's prefix. Am I doing something wrong, or does flask-restplus not take the path prefix into account? If it doesn't, the blueprint has a path_prefix property to obtain it.

Representing output type without using marshal and marshaling basic types

I have a very simple method that is generating a list of strings and returning it. Currently the only way that the swagger docs will show the response type is if the method has @api.marshal_with() or @api.marshal_list_with(). However, neither of these methods seem to work appropriately with simple objects. Below is an example:

from flask import Flask
from flask.ext.restplus import Api, Resource, fields
from nltk.tokenize import word_tokenize
import os, nltk

app = Flask(__name__)
api = Api(app, version='1.0', title='NLP Tools API',
    description='A set of easy to use NLP tools powered by NLTK.',
)

ns = api.namespace('nlptools/api/v1', description='NLP operations')
parser = api.parser()
parser.add_argument('text', type=str, required=True, help='The text to be processed', location='json')

@ns.route('/tokenize')
@api.doc(responses={400: 'Invalid request'})
class Tokenizer(Resource):
    @api.doc(parser=parser, description='Tokenizes the input text into a list of strings.')
    @api.marshal_list_with(fields.String)
    def post(self):
        args = parser.parse_args()
        return word_tokenize(args['text'])

if __name__ == '__main__':
    app.run(host=os.getenv('VCAP_APP_HOST', '127.0.0.1'), port=int(os.getenv('VCAP_APP_PORT', '5000')), debug=True)

Running this with a REST client with a json body of {"text":"this is a test sentence to tokenize."} returns the following error:

Traceback (most recent call last):
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/usr/local/lib/python3.4/site-packages/flask_restful/__init__.py", line 265, in error_router
    return original_handler(e)
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.4/site-packages/flask/_compat.py", line 32, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.4/site-packages/flask_restful/__init__.py", line 265, in error_router
    return original_handler(e)
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.4/site-packages/flask/_compat.py", line 32, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python3.4/site-packages/flask_restful/__init__.py", line 446, in wrapper
    resp = resource(*args, **kwargs)
  File "/usr/local/lib/python3.4/site-packages/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/usr/local/lib/python3.4/site-packages/flask_restful/__init__.py", line 550, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/usr/local/lib/python3.4/site-packages/flask_restful/__init__.py", line 647, in wrapper
    return marshal(resp, self.fields, self.envelope)
  File "/usr/local/lib/python3.4/site-packages/flask_restful/__init__.py", line 602, in marshal
    for k, v in fields.items())
AttributeError: type object 'String' has no attribute 'items'

I have also tried return json.dumps(word_tokenize(args['text'])) and @api.marshal_with(fields.List(fields.String)) with the same result in all four cases. Is there an alternative way to represent the response object? Is there a way to appropriate marshal basic fields?

Thanks.

Support ORM (MongoKit) models?

I've been trying to generate ApiModels from from MongoKit models:

Consider the following MongoKit model:

@api.model() # this would be awesome
class User(Document):
    structure = {
        'name': unicode,
        'email': unicode,
    }
    use_dot_notation=True

Currently I've tried this

user_model = api.model('User', fields=User.structure)

Kind of expected this to work automagically, but looks like I'm missing something.

File "/home/mike/.virtualenvs/cmdb/lib/python2.7/site-packages/flask_restplus/swagger.py", line 357, in serialize_schema
    raise ValueError('Model {0} not registered'.format(model))
ValueError: Model <function wrapper at 0x7fb5a6cb1578> not registered

Not sure how the whole model mapping process works, could you please provide some details?

Thanks!

[proposal] better support for security requirements

What I'm proposing, and willing to implement and contribute is a SecurityRequirement class, possibly with subclasses like OAuth2SecurityRequirement. defining an api with these requirements would look like this:

oauth2_req = OAuth2SecurityRequirement(name="needsuser", scopes=["scope1", "scope2"], flow="implicit", authorization_uri="http://example.com/authorize")
apikey_req = ApiKeyRequirement(name="apikey", param_name="key", in="query")

to require either one of these api requirements api-wide, you'd pass an array of instances to the API constructor.


```python
Api(title="my apy", version="v1", security_requirements=[
    apikey_req,
    oauth2_req("scope1")
])

Note that oauth2 requirement instances are callable, so you can pass in required scopes.

I'd be very much willing to implementthis and contribute the code back to this project if you're interested.

Bulk json upload in a PUT

Hello,

I am trying to do a bulk load of variables in a put.

{
'key1': 'value1',
'key2': 'value2',
'key3': 'value3'
}

So instead of presenting a form for each field, I just need a field that allows them to do that and a visable model that shows what is expected (in swagger). How would I go about doing that? I can't seem to find any documentation on its implementation. Thanks

Model schema is missing from swagger-ui in a special case.

I am describing the response model of an endpoint using the api.marshal_with and api.model functions.

The desired model is:

speed_statistics_sample = api.model('SpeedSample', {
    'timestamp': fields.DateTime(),
    'rate': fields.Float()
})

speed_statistics_period = fields.List(fields.Nested(speed_statistics_sample))

speed_statistics_link = api.model('LinkSpeed', {
    'rx': speed_statistics_period,
    'tx': speed_statistics_period
})

However on the swagger-ui it cannot decode the nested models. On Model Schema page thefields rx and tx says null, while on Model page it understands that depends on SpeedSample model, it does not provide its information:
model_missing
model_schema_missing


The wierd thing is that if I change a bit the api and remove the List field for one member, everything is fixed, though this is not the desired model that I want to describe.

speed_statistics_sample = api.model('SpeedSample', {
    'timestamp': fields.DateTime(),
    'rate': fields.Float()
})

speed_statistics_period = fields.List(fields.Nested(speed_statistics_sample))

speed_statistics_link = api.model('LinkSpeed', {
    'rx': fields.Nested(speed_statistics_sample),
    'tx': speed_statistics_period
})

Then the swagger-ui is working as expected:
model
model_schema

Notice, that marshaling was perfect on all cases, it is only an issue of documentation.

Non URL Encoded input field support request

I have a particular situation where I want to allow the swager user to be able to type an arbitrarily formatted query string and have it work in the "try it". The problem right now is that the string is urlencoded and thus breaks when it's run. Basically, I want the same input that I put into the query string to make it through to the 'try me' because I don't know all of the possible query keys in advance:

screen shot 2015-05-07 at 3 07 00 pm

Note the query string input, and the URLEncoded result in 'try me.' I need a clean way to tell it not to urlencode.

Nested Marshal inner Nested List isn't registered into swagger definitions

I tried to create a swagger documentation for my service that responds as follow:

{
  "error": null,
  "result": {
    "applicationName": "MyApp.Rest",
    "checks": [
      {
        "error": "",
        "name": "Configuration",
        "ok": true
      }
    ],
    "executedAt": "2015/03/31 15:50:53.731201",
    "ok": true,
    "serverVersion": "0.10.1"
  },
  "status": "ok"
}

To do the swagger documentation, I wrote the follow code fragment and I associated it with the get function using @api.marshal_with(health_check_model).

...
Check = api.model('Check', {
    'ok': fields.Boolean(required=True, description='True if all is fine, false otherwise'),
    'name': fields.String(required=True, description='Check item name'),
    'error': fields.String(required=False, description='Shows the error description if any problem occurred'),
})

health_check = api.model('HealthCheck', {
    'applicationName': fields.String(required=True, description='Application Name'),
    'serverVersion': fields.String(required=True, description='Current Server Version'),
    'ok': fields.Boolean(required=True, description='True if all is fine, false otherwise'),
    'checks': restplus.fields.List(restplus.fields.Nested(Check)),
    'executedAt': fields.String(required=False, description='When the validation check happened'),
})

health_check_model = default_scheme = api.model('HealthCheckResponse', {
    'result': fields.Nested(health_check, description='Health Check model'),
    'status': fields.String(required=False, description='Status of response'),
    'error': fields.String(required=False, description='Some error'),
})

However, the swagger.json has been generated without the Check class:

...
   "HealthCheck":{  
      "properties":{  
         "applicationName":{  
            "description":"Application Name",
            "type":"string"
         },
         "checks":{  
            "items":{  
               "$ref":"#/definitions/Check",
               "required":true
            },
            "type":"array"
         },
         "executedAt":{  
            "description":"When the validation check happened",
            "type":"string"
         },
         "ok":{  
            "description":"True if all is fine, false otherwise",
            "type":"boolean"
         },
         "serverVersion":{  
            "description":"Current Server Version",
            "type":"string"
         }
      },
      "required":[  
         "applicationName",
         "serverVersion",
         "ok"
      ]
   },
   "HealthCheckResponse":{  
      "properties":{  
         "error":{  
            "description":"Some error",
            "type":"string"
         },
         "result":{  
            "$ref":"#/definitions/HealthCheck",
            "description":"Health Check model"
         },
         "status":{  
            "description":"Status of response",
            "type":"string"
         }
      },
      "required":[  
         "result"
      ]
   }
...

Do you know what I'm doing wrong?

Encapsulates the event in json format Missing required parameter in the JSON body

I was wondering, when the following is my data model that everybody sees
{
"type": "string",
"siteId": "string",
}

Then why do I have to encapsulate it with the argument passed in add_argument as follows?
{"event":{
"type": "VNF",
"siteId": "DC1",
}}

How would the user possibly know that they are to encapsulate in with "event"? If I don't I get the following error:

{
"message": {
"event": "(Encapsulates the event in json format) Missing required parameter in the JSON body"
}
}

Thanks in advance

Example using blueprints?

Do you have an example using flask-restplus with Blueprints rather than just a simple API?

Thanks!
Kathy

Getting "View function mapping is overwriting an existing endpoint function" when register a class with the same name

I have tested several use-cases and bumped into an issue of that I cannot have a classes of the same name even when they are mounted to different namespaces/routes.

Based on the todo_blueprint.py example, I added the following changes:

*************** api = Api(api_v1, version='1.0', title='
*** 8,13 ****
--- 8,14 ----
  )

  ns = api.namespace('todos', description='TODO operations')
+ ns2 = api.namespace('todos2', description='TODO operations')

  TODOS = {
      'todo1': {'task': 'build an API'},
*************** parser = api.parser()
*** 33,39 ****
  parser.add_argument('task', type=str, required=True, help='The task details', location='form')


- @ns.route('/<string:todo_id>')
  @api.doc(responses={404: 'Todo not found'}, params={'todo_id': 'The Todo ID'})
  class Todo(Resource):
      '''Show a single todo item and lets you delete them'''
--- 34,39 ----
*************** class Todo(Resource):
*** 60,65 ****
--- 60,67 ----
          TODOS[todo_id] = task
          return task

+ ns.route('/<string:todo_id>')(Todo)
+ ns2.route('/<string:todo_id>')(Todo)

  @ns.route('/')
  class TodoList(Resource):

But when I run this, I get the following traceback:

Traceback (most recent call last):
  File "restplus_example_blueprints.py", line 86, in <module>
    app.register_blueprint(api_v1)
  File "env/lib/python3.4/site-packages/flask/app.py", line 62, in wrapper_func
    return f(self, *args, **kwargs)
  File "env/lib/python3.4/site-packages/flask/app.py", line 889, in register_blueprint
    blueprint.register(self, options, first_registration)
  File "env/lib/python3.4/site-packages/flask/blueprints.py", line 153, in register
    deferred(state)
  File "env/lib/python3.4/site-packages/flask/blueprints.py", line 172, in <lambda>
    s.add_url_rule(rule, endpoint, view_func, **options))
  File "env/lib/python3.4/site-packages/flask_restful/__init__.py", line 162, in _blueprint_setup_add_url_rule_patch
    view_func, defaults=defaults, **options)
  File "env/lib/python3.4/site-packages/flask/app.py", line 62, in wrapper_func
    return f(self, *args, **kwargs)
  File "env/lib/python3.4/site-packages/flask/app.py", line 984, in add_url_rule
    'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: api.todo

Ability to enter schema via dict

Hi,

Is it possible to enter schema via dict rathern the using api.Model??

Most of our config uses jsonschema which we want an api to be able to modify the config for the application. There is quite alot of jsonschema and would prefer to use our existing rather then duplicate to api.Model

IE:

sch = {
    'type': 'object',
    'properties': {
        'force': {'type': 'boolean'},
    }
}


@server_api.route('/someapi/')
class SomeAPI(Resource):

    @api.expect('SomeAPI', sch)
    def post(self)

Thanks!

Optimize performances

Some things make API instanciation very longs (seen in testing on some projects)

deepcopy usage cost way too much.

Lost in examples

Hello,

First, thanks for your very great work !
I'm a little lost with examples, I would like to create a complete CRUD with a simple model named Role which have 2 fields : "name" and "description".

Here is the complete file : https://gist.github.com/Seraf/23d0d34e11c38f922f4b

I think most of the docs/api is correct, but I guess I have a misunderstanding about the parser and how to use it. Sometimes examples use parsers, sometimes the class fields.Raw (Person) ...

Can you give me some advice/comment about it please ?

Thanks

Getting 400 Bad request when using the swagger-ui.

Using swagger-ui I always get 400 Bad request if there is at least one argument for parsing. For endpoints that have no parameters it works just fine. Notice that the API works with no problem if I consume it from any other client, even the same browser by just requesting the URL in a different window.

After investigation I found that it was a problem of swagger-ui client that it always puts the 'Content-type: application/json` even for GET requests. Werkzeug or Flask(not sure) finds illegal putting content-type header without having any HTTP payload (the case of GET), thus the 400 Bad request.

No way to configure .../swagger.json to go over HTTPS?

Hello,

I have an application deployed using Flask-RESTPlus. Everything works nicely when it goes over http, but soon as I switch to https, it can't load the swagger.json because it is making requests to http://host/swagger.json and not https://host/swagger.json

The endpoints are registered properly with blueprints, because if I manually go to https://host/swagger.json, I get the correct JSON. However, the generated swagger page tries to load the JSON from a http endpoint, instead of the correct https endpoint.

Is there any way to fix this?

Thanks

Ui url is fixed and cannot be changed

In api.py:136:

self.blueprint.add_url_rule('/', 'root', self.render_root)

I think this url should be customizable. We not always want to expose ui on known uri.

Flask-Login

There is a non magic way to use login with that lib??

Any support for Fixed fields such as Host / Tags and Vendor fields?

Hi,

I started implementing a project with your library, and so far its great. I found it intuitive and relatively easy to use. A few things that aren't available are top level tags like Host and additional tags on the path (which for now is only used by the namespace).

I've made modifications locally, but wasn't sure if this was functionality that was going to be forthcoming.

Thanks!
Kelvin

Problem with PUT method when the param field has the same name than a field in the model

Hello,

I decided to use name instead of id as argument to find my role.
I updated it like this : https://gist.github.com/Seraf/23d0d34e11c38f922f4b

The get(name) and delete(name) works great. But the PUT method has a problem :
http://127.0.0.1:5000/api/1/core/role/{name} -> the name here isn't replaced by the name value I give
On the get function, it uses the name I give :
http://127.0.0.1:5000/api/1/core/role/test

I think the problem is that PUT method use the name of my model and not the param field in my decorator.
I think I can workaround the problem using "rolename" as param but it won't make sense on my PUT method to have rolename param and name param with the same value.
I hope I'm clear in my explanation :)

Thanks !

Nested models error

Models setup:

api.model(name=u'User', model={
    'login': fields.String(
        description=u'Login',
        required=True,
    ),
    'public': fields.Nested({
        'email': fields.String(
            description=u'Email (if email public)',
            required=False,
        ),
        'nickname': fields.String(
            description=u'Nickname',
            required=False,
        ),
    }),
})

api.model(name=u'Register result', model={
    'errors': fields.List(
        fields.String,
        required=False,
        description=u'Error list',
    ),
    'user': fields.Nested(
        api.models['User'],
        description=u'created user object',
    ),
})

Error on swagger ui request:

Traceback (most recent call last):
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restful/__init__.py", line 263, in error_router
    return original_handler(e)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restful/__init__.py", line 260, in error_router
    return self.handle_error(e)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restful/__init__.py", line 263, in error_router
    return original_handler(e)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restful/__init__.py", line 260, in error_router
    return self.handle_error(e)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restful/__init__.py", line 431, in wrapper
    resp = resource(*args, **kwargs)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restful/__init__.py", line 521, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restplus/api.py", line 150, in get
    return Swagger(self.api).as_dict()
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restplus/swagger.py", line 248, in as_dict
    'definitions': self.serialize_definitions() or None,
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restplus/swagger.py", line 403, in serialize_definitions
    for name, model in self._registered_models.items()
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restplus/swagger.py", line 403, in <genexpr>
    for name, model in self._registered_models.items()
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restplus/swagger.py", line 388, in serialize_model
    prop = field_to_property(field)
  File "/home/maciek/.virtualenvs/pudelek-auth/lib/python2.7/site-packages/flask_restplus/swagger.py", line 116, in field_to_property
    prop = ref(nested_field.__apidoc__['name'])
AttributeError: 'dict' object has no attribute '__apidoc__'

Embedded Swagger UI + restful prefix = 404 Not Found

Given I have a flask_restful Api with prefix='1.0/'
Given I have a flask_restplus route under 1.0/test
When I do a GET /1.0/test from the embedded Swagger UI (which is under /, instead of /1.0)
Then the Swagger UI does a GET /test/ and Flask answers 404 Not Found

There's a bit of code reproducing the issue here : https://gist.github.com/sduthil/74cf23da60c761f082bd

Tested with flask_restful 0.3.1 and flask_restplus 0.4.0.
This feature worked with flask_restful 0.2.12 and flask_restplus 0.2.4.

Any idea where this comes from ?

Maximum recursion level exceeded

The latest version (0.8.0) has introduced a pretty significant issue that eventually leads to the following stack trace or something similar:

2015-10-08 14:29:59.008 - [ERROR] (12366) (MainProcess)(MainThread) --> Caught unhandled exception: maximum recursion depth exceeded
Traceback (most recent call last):
  File "/someapp/env/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/someapp/env/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/someapp/env/lib/python2.7/site-packages/flask_restful/__init__.py", line 471, in wrapper
    resp = resource(*args, **kwargs)
  File "/someapp/env/lib/python2.7/site-packages/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/someapp/env/lib/python2.7/site-packages/flask_restful/__init__.py", line 581, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/someapp/env/lib/python2.7/site-packages/flask_restplus/resource.py", line 27, in wrapper
    return func(*args, **kwargs)
  File "/someapp/env/lib/python2.7/site-packages/flask_restplus/resource.py", line 27, in wrapper
    return func(*args, **kwargs)
  File "/someapp/env/lib/python2.7/site-packages/flask_restplus/resource.py", line 27, in wrapper
    return func(*args, **kwargs)
  ...
  File "/someapp/env/lib/python2.7/site-packages/flask_restplus/resource.py", line 27, in wrapper
    return func(*args, **kwargs)
  File "/someapp/env/lib/python2.7/site-packages/flask_restplus/resource.py", line 20, in wrapper
    data = request.get_json()
  File "/someapp/env/lib/python2.7/site-packages/werkzeug/local.py", line 338, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/someapp/env/lib/python2.7/site-packages/werkzeug/local.py", line 297, in _get_current_object
    return self.__local()
  File "/someapp/env/lib/python2.7/site-packages/flask/globals.py", line 18, in _lookup_req_object
    top = _request_ctx_stack.top
  File "/someapp/env/lib/python2.7/site-packages/werkzeug/local.py", line 163, in top
    return self._local.stack[-1]
RuntimeError: maximum recursion depth exceeded

Traced the problem to the following lines here:

class Resource(restful.Resource):

    def __init__(self, api, *args, **kwargs):
        self.api = api
        if self.validate_payload not in self.method_decorators:
            self.method_decorators.insert(0, self.validate_payload)

The if self.validate_payload not in self.method_decorators: always returns true and just keeps adding the decorator over and over because method_decorators is a class level property declared as a list (mutable python object problem) and Resource is instantiated as a new object each time.

So when running that list changes the following ways:

[]
127.0.0.1 - - [08/Oct/2015 14:35:51] "GET /api-aw/jobs HTTP/1.0" 200 -
[<bound method JobsList.validate_payload of <app.api.resources.someapp.jobs.JobsList object at 0x1fccc90>>]
127.0.0.1 - - [08/Oct/2015 14:35:51] "GET /api-aw/jobs HTTP/1.0" 200 -
[<bound method JobsList.validate_payload of <app.api.resources.someapp.jobs.JobsList object at 0x1fccb50>>, <bound method JobsList.validate_payload of <app.api.resources.someapp.jobs.JobsList object at 0x1fccc90>>]
127.0.0.1 - - [08/Oct/2015 14:35:51] "GET /api-aw/jobs HTTP/1.0" 200 -
[<bound method JobsList.validate_payload of <app.api.resources.someapp.jobs.JobsList object at 0x1fccb10>>, <bound method JobsList.validate_payload of <app.api.resources.someapp.jobs.JobsList object at 0x1fccb50>>, <bound method JobsList.validate_payload of <app.api.resources.someapp.jobs.JobsList object at 0x1fccc90>>]
127.0.0.1 - - [08/Oct/2015 14:35:51] "GET /api-aw/jobs HTTP/1.0" 200 -
[<bound method JobsList.validate_payload of <app.api.resources.someapp.jobs.JobsList object at 0x2147fd0>>, <bound method JobsList.validate_payload of <app.api.resources.someapp.jobs.JobsList object at 0x1fccb10>>, <bound method JobsList.validate_payload of <app.api.resources.someapp.jobs.JobsList object at 0x1fccb50>>, <bound method JobsList.validate_payload of <app.api.resources.someapp.jobs.JobsList object at 0x1fccc90>>]

This eventually leads to the maximum recursion problem. One option is to just do the following:

class Resource(restful.Resource):

    def __init__(self, api, *args, **kwargs):
        self.api = api
        self.method_decorators = [self.validate_payload]

This does mean though you can't do what is explained here any longer.

Needless to say this is pretty significant issue because pretty soon anyone using this is going to start having some pretty major problems as soon as they get enough requests for this to manifest itself.

templates/swagger-ui-libs.html includes incorrect javascript file for handlebars

First, I want to say that I have only a vague understanding of how the javascript dependencies are installed for restplus, so right now I can't say why this is happening.
But.
In my virtualenv, in lib/python2.7/site-packages/flask_restplus/static/bower/swagger-ui/dist/lib directory, there's the handlebars-2.0.0.js file, while swagger-ui-libs.html tries to include handlebars-1.0.0.js.

params are urlencoded

Given a resource like this

@api.route('/foo', endpoint = 'foo')
class Foo(Resource):
@api.doc(summary = "Retrieve by foo",
description = "The foo resource allows you to find an object that has a particular foo assigned",
params = {'foo':'The foo to locate'},
responses = {404 : 'foo not found', 422 : "foo format invalid"})
def get(self):
parser = reqparse.RequestParser()
parser.add_argument("foo", type = str, required = True,
location = ('values', 'json', 'form','data'),
help = "Missing 'foo' argument")
args=parser.parse_args()
foo=args['foo']
return __find_foo(foo)

The 'Try it out' functionality will url encode values passed to foo

so a foo id of 00:1c:73:69:e1:6f is
called as http://localhost:5000/foo?foo=00%3A1c%3A73%3A69%3Ae1%3A6f which returns a 400 bad request.

I'm guessing there is something I'm not doing with regards to properly handling urlencoded or there is some way to not have it urlencode on the "try it" feature.

Splitting up API library into multiple files

I've tried several different ways to split up the API files into separate python source but have come up empty. I love the additions to flask-restplus but it appears that only the classes within the main python file are seen. Is there a good example of how to do this? In Flask-Restful it was a bit simpler as you could just add the resource and point to a different python file that got imported.

Refactor tests

Test files starts to be too dense.
Refactor to split into more files.

Issue using fields.List

I am having trouble understanding how to use fields.List in the context of a model. I am trying to create a model that is a list of objects. Each of those objects contains a field that is also a list. For example:

[ {'name': 'some_name',
   'pets': ['cat','dog]
  },
 {'name': 'some_other_name',
  'pets': ['fish', 'chicken', 'dog']
 } ]

When I try to create a list using api.model, like so:

mymodel = api.model('myModel', {
        'name': fields.String(description='name'),
        'pets': fields.List(description='pets', required=True),
    })

I get the following traceback:

Traceback (most recent call last):
File "/somefile.py", line 120, in Options
'pets': fields.List(description='pets', required=True),
File "/usr/local/lib/python2.7/dist-packages/flask_restplus/fields.py", line 16, in init
super(DetailsMixin, self).init(_args, *_kwargs)
File "/usr/local/lib/python2.7/dist-packages/flask_restplus/fields.py", line 10, in init
super(DescriptionMixin, self).init(_args, *_kwargs)
TypeError: init() takes exactly 2 arguments (1 given)

Please advise.

"Can't read swagger JSON" with url_prefix='/' in a blueprint

Hi,

I have a current flask-restful server that we want to upgrade and add blueprints so that we can root different versions with "v2", "v3", etc.To be backward compatible, we would like do the following:

FLASK_APP = flask.Flask(__name__)
blueprint = flask.Blueprint('v1', __name__, url_prefix='/')
API = restplus.Api(blueprint, version='1.0', ui=False,
                   title='DynDNS REST Server',
                   description='DynDNS\'s multiple endpoint REST server')

@blueprint.route('docs/', endpoint='docs')
def swagger_ui():
    return restplus.apidoc.ui_for(API)

FLASK_APP.register_blueprint(blueprint)
FLASK_APP.register_blueprint(restplus.apidoc.apidoc)

The old urls work fine, e.g. /foo, however, when I navigate to /docs/, I get "Can't read swagger JSON from..." in the browser; it doesn't seem to recognize where to find sawgger.json

@api.doc can't handle docstrings from decorated functions

I think I have spot a bug which operates as follows. If I pass the @api.doc decorator a function that has already been decorated several times, it fails to set its docstring in the swagger summary bar. Exemple :

@ns_groups.route(
    '',
    endpoint='group',
)
class Group(Resource):
    @api.doc(parser=get_parser)
    @auth.login_required
    def get(self):
        """Retrieves a group"""

        args = get_parser.parse_args()
        ... some more code

Will give me the correct Swagger documentation, whereas:

    @api.doc(parser=delete_parser)
    @auth.login_required
    @admin_required
    def delete(self):
        """Deletes a group
        """

        args = delete_parser.parse_args()
        ... some more code

Will not set anything, regardless where in the decorator chain I put @api.doc.

Altough it works if I only use two decorators.

Update pip

Hi,

My projects 2.6 tests are failing due to the api.validate conflict bug. It's already fixed but the package on pip has not been updated.

Any chance we can get the package on pip built/updated?

Add @api.response decorator

Add an @api.response decorator shortcut.

Example:

@api.route('/somewhere/')
class MyResource(Resource):
    @api.response(403,  'Not Authorized')
    @api.response(somemodel, headers={}, default=True)
    def get(self, id):
        return {}
'''

Improve documentation

Documentation starts to get bigger, there is a lot more cases to describe.

Improvements could be:

  • Add more examples (modular api registeration, more models....)
  • Document internal behavior
  • More docstring (API section)
  • Document security
  • Customization documentation / samples

Exception is raised when init_app() is called more than once

The culprit is this line of code in init_app():

self.add_resource(self.swagger_view(), '/swagger.json', endpoint='specs', doc=False)

The self.swagger_view() method returns a new class each time. And, because of that, the code in the following if-block gets executed: https://github.com/flask-restful/flask-restful/blob/0.3.1/flask_restful/__init__.py#L391

This is very inconvenient for me, as because of this issue I can't create more than one class for my functional tests: for each such class, I must call my application factory, which, in turn, imports my Api instance and calls init_app() on it.

The fastest solution that I see right now is to just make the addition of the specs optional via a new kwarg. I can create a pull request for this.

POST adding extra header

Using the 0.8.0 version I discovered an issue today when trying to use the swagger UI to test a POST. An extra header (--header "Content-Type: application/json") is being added to the curl command, and this is causing the my FLASK server to error out and return 400 error code. If I manually execute the curl command without the extra header it completes successfully.

This seems to be a similar issue to this one, that is in reference to a GET. #15

Is it possible to document a method within a class by using @api.doc() outside of the class?

Here is what I would like to do:

@api.doc(documentation for GET method, documentation for PUT method)
class A():
def get():
pass
def put():
pass

I couldn't find any solution on flask-restplus documentation other than defining doc explicitly before each method.
Any explanation on how to achieve this task or whether this is impossible to achieve or any pointer to this context would really help. Thank you @noirbizarre Hope to hear something back from you.

Documenting Input Body

I'm having trouble getting JSON body inputs documented in swagger and working the way I want.

My end goal is to setup a POST request that is JSON that looks like {"type": "foobar"}.

I want to be able to validate the input coming in so I first tried doing this using the following parser:

parser = api.parser()

packages_post = parser.copy()
packages_post.add_argument(
        "data",
        required=True,
        location="json",
        help="The type of package to create."
)

The problem with this method is it doesn't really document what the schema looks like very well:

image

I then went with a model and used the body option in api.doc() which did document things well but doesn't do validation:

package = api.model(
        "Package",
        {
                "type": fields.String(
                        description="The type of package to create.",
                        required=True
                )
        }
)

image

Alright, so I figure I can use a combination of the two to get both the right documentation and validation:

package = api.model(
        "Package",
        {
                "type": fields.String(
                        description="The type of package to create.",
                        required=True
                )
        }
)

parser = api.parser()

packages_post = parser.copy()
packages_post.add_argument(
        "package",
        type=package,
        location="json"
)

I noticed this pattern in the tests and it almost works however now the input needs to be {"package": {"type": "foobar"}} which doesn't get documented very well.

The only way I can see to get things to work the way I want is to define both a parser and a model with the same exact information which is a bit ugly and redundant.

Is there something I might be missing to make this a bit better? Perhaps something I can look at adding to make this possible?

New version to pip?

Just curious if you are planning on releasing a new version soon? There are a couple of things that are in the code base that I would like to use but they are newer than the version out on pip.

I left a comment on an old closed item and I'm not sure if you get notified about that so I'm creating this issue.

Thanks for creating this project. It's been a big help for me!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.