Code Monkey home page Code Monkey logo

flask-classful's People

Contributors

a-r-g-v avatar antgel avatar apiguy avatar bivald avatar blurrcat avatar bulv1ne avatar datphan avatar davidism avatar dependabot[bot] avatar digitaleye-llc avatar esbullington avatar gitter-badger avatar hieptranquoc avatar hjc avatar hoatle avatar incognick avatar j-dunham avatar janpeterka avatar lucasg2000 avatar mattbillenstein avatar maxcountryman avatar njl avatar pre-commit-ci[bot] avatar raizyr avatar rufman avatar shuhaowu avatar slhawkins avatar sweenu avatar uniphil avatar unixxman 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

flask-classful's Issues

rename flask-classy to flask-classful

  • rename repo
  • update name Flask-Classy to Flask-Classful
  • update the module name from flask_classy to flask_classful (note that this is a broken change, users must update module name from flask_classy to flask_classful)
  • create a new tag for v0.9.0 with its new name and publish it to pypi
  • update flask-classy.teracy.org docs to flask-classful.teracy.org

ref: apiguy/flask-classy#80

should keep the original license

I changed the original license to add Teracy copyright, however, I see that this is not the right way to do.

So let's revert and keep the original license instead.

enhance 3rd party decorators

I'm having issues with flask-apispec using flask-classful. The issue is that apispec attaches information to the decorated function. I tried to fix it within their code but it is very complicated.

I fixed this in flask classful make_proxy_method to decorate the proxy rather than decorate the bound instance method. Anyone apposed to this fix? I'll submit a PR to aid the discussion.

adding __init__ method to classes created

how can i achieve something like this
class MyBaseView(FlaskView): def __init__(self, model): self.model = model
cos i get error TypeError: init() missing 1 required positional argument: 'model'
after registering and running my app

injection of dependencies into view

Hello,

What is the way to inject dependencies into the views?
Is there a way I can have and pass stuff into __init__, say a database handle or any other kind of service?

Thanks

define the roadmap for v0.15.0

v0.14.0 is going to be released soon, it's time for us to figure out what's next for flask-classful.

  • The first thing in my mind is to create more example, tutorials and integration examples, best practices for flask-classful to build robust REST APIs.

  • What's next? We need to figure this out together, there are some issues that we need to discuss to see if it's a fit for flask-classful (for example, IOC issue, etc).

should allows flask.jsonify to return status codes and headers

for PR: #16

Recently, we switched from Flask Classy to Flask Classful and discovered that all our routes using flask.jsonify with custom headers and status codes weren't working. For example:

def post(self):
return jsonify({"success": True}), 201, {"X-CUSTOM-HEADER": "1"}
would return the proper JSON response but would be missing the headers and status code. Currently, we've had to change all those routes to:

def post(self):
return make_response(jsonify({"success": True}), 201, {"X-CUSTOM-HEADER": "1"})
This is a definite regression from Flask Classy and this PR remedies that.

Shoutout to @hjc1710 for pair programming this with me.

subdomains of the methods

It's not possible to register different methods in different subdomains due to next code in
FlaskView.register:

if not subdomain and sub:

      subdomain = sub

...

app.add_url_rule(rule, endpoint, proxy, subdomain=subdomain, **options)

Question on REST hierarchy

Hey, we have been using flask-classful for a while now and it has been awesome.
Really appreciate you taking this repo over!

Anyway, my question has to deal with architecting views for models who are children.
When i started the architecture it was my first flask app and i couldn't find any help so i made up a lame strat. At the time I was still using flask-classy, hadn't yet figured out it was taken over, and there have been several things that i thought were impossible until i thankfully replaced classy with classful so i am wondering if this question is similar.

With the code below, is there any way to make views "smart" so they know about their parent's rest routes without the repetition in route_prefix. Now that i have 50+ models I would really like to be doing the better way for this architecture (if there is one), before i have 100+ models lol.

I have tried inheritance, and different combinations of route_prefix with route_base while following how they get built with the classful internals and i couldn't find a good strategy.

class ParentView(FlaskView):
  """View for Parent model"""
  route_prefix = '/api/v1/parent'

  def get(self, parent_id: int):
    pass


class ChildView(FlaskView):
  """View for Child model"""
  route_prefix = '/api/v1/parent/<int:parent_id>/child'

  def get(self, parent_id: int, child_id: int):
    pass


class GrandKidView(FlaskView):
  """View for GrandKid model"""
  route_prefix = '/api/v1/parent/<int:parent_id>/child/<int:child_id>/grandkids'

  def get(self, parent_id: int, child_id: int, grandkid_id: int):
    pass

As always thanks for any help!

View methods not working as expected (?)

I'm working on a rest api for a book database and have factored out two views: authors and books. The problem I'm having is that a basic GET for either an author or a book (http://localhost:5000/api/v1/[authors, books]/) works fine, but I'm getting a 404 error if I want to get a specfic author or book (http://localhost:5000/api/v1/author/1/ ).

[What the client sees]

$ curl -i http://localhost:5000/api/v1/authors/1/
HTTP/1.0 404 NOT FOUND
Content-Type: text/html
Content-Length: 233
Server: Werkzeug/0.11.11 Python/2.7.11
Date: Sun, 20 Nov 2016 23:04:38 GMT

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server.  If you entered the URL manually please check your spelling and try again.</p>

[Response from api]

127.0.0.1 - - [20/Nov/2016 18:04:38] "GET /api/v1/authors/1/ HTTP/1.1" 404 -

Here's what the relevant code for the AuthorsView class looks like:

class AuthorsView(FlaskView):
    route_prefix = '/api/v1/'

    def get(self, author_id=None):
        if author_id:
            author = Author.query.filter_by(author_id=author_id).first()
        #    if not author:
        #        raise InvalidUsage(
        #            'Author with id of %i not found.' % id,
        #            status_code=404)
            resp = jsonify(author.to_dict())
            resp.status_code = 200
            return resp
        authors = [a.to_dict() for a in Author.query.all()]
        #if not authors:
        #    raise InvalidUsage(
        #        'Authors not found.' % id, status_code=404)
        resp = jsonify(authors)
        resp.status_code = 200
        return resp

Any ideas what's going on here?

Internationalization with flask-classful

I'm about to apply i18n into flask-classful-based project,
but I still didn't find the way of using Flask-babel with flask-classful.

how can i do this? does i18n feature can work with flask-classful?

Standard repo tidying.

@hoatle - I think adding some small docs and standard OSS repo items would be good, such as a pull request template, contributor's guidelines, etc.

Let me know your thoughts and if you have something you want to do for this in mind, otherwise I can slowly get it done.

add_url_rule() got multiple values for argument 'endpoint'

The docs clearly states that you can pass to register any additional params that add_url_rule can accept.
The problem is that if y pass endpoint='home' (a common param to add_url_rule) to the register function, then the following exception raises:

add_url_rule() got multiple values for argument 'endpoint'

That's because flask-classfull is not extracting from rule_options the posible user supplied values for the route_name (also known as 'endpoint').

Line 139 instead:
route_name = cls.build_route_name(name)

should be:
route_name = rule_options.get('endpoint') or cls.build_route_name(name)

or just simply change the register function signature to accept an endpoint parameter and then:
route_name = endpoint or cls.build_route_name(name)

inspect.getargspec() is deprecated, use inspect.signature() or inspect.getfullargspec()

Hi @hoatle, thank you for maintaining flask-classful!

After migration to Python3.7 I am being flooded with deprecation warning - could you have a look at it?

virtualenv/python3.7.1/lib/python3.7/site-packages/flask_classful.py:382: DeprecationWarning:
inspect.getargspec() is deprecated, use inspect.signature() or inspect.getfullargspec()

It might be that simple swapping of the order of this try-except would fix it:
https://github.com/teracyhq/flask-classful/blob/42fa5fce1fa97b1f00813b4ce0dd13ebebdb28cc/flask_classful.py#L446-L449

should improve the representations behavior

hjc 6 hours ago
Couple things. First off, to handle a missing content type from representations we should either throw a specific exception or provide the usage of like a default key in the representations dictionary that is a catch-all function that can always be used. Alternatively, we should just return the data we were given. I don't like using the first key in the dictionary, because dictionary ordering isn't guaranteed until Py3.6, in earlier versions you'd get a random key every time and that sounds SUPER frustrating.

from: https://github.com/teracyhq/flask-classful/pull/71/files#r141177560

before_request() got multiple values for argument 'name'

test code:

from flask import Flask
from flask_classful import FlaskView, route

# we'll make a list to hold some quotes for our app
quotes = [
    "A noble spirit embiggens the smallest man! ~ Jebediah Springfield",
    "If there is a way to do it better... find it. ~ Thomas Edison",
    "No one knows what he can do till he tries. ~ Publilius Syrus"
]

app = Flask(__name__)

class QuotesView(FlaskView):
    def before_request(self, name):
        self.a = 1

    def index(self):
        return "<br>".join(quotes)

    @route("/<name>", methods=["GET"])
    def get_a(name):
        return self.a

QuotesView.register(app)

if __name__ == '__main__':
    app.run(port=1234)

curl

TypeError: before_request() got multiple values for argument 'name'

Should allow specifying excluded methods from becoming routes

In previous versions (not sure of the range, because I don't know when this behavior was introduced) of Flask Classful, it was possible to have a public method in your view class and not have it automatically registered as a route. Take for example:

from flask import request
from flask_classful import FlaskView

class BaseView(FlaskView):
    def copy_form_data(self):
         return request.form.copy()

In this example, BaseView.copy_form_data is registered as a route on all views that extend from BaseView. IMHO this isn't desired behavior, but whatevs.

So another issue related to this that I discovered (and maybe related to #29) is that I cannot make BaseView.copy_form_data into a static method because a flask_classful.DecoratorCompatibilityError is raised when it's encountered.

I have found that the only way around this restriction is to make that method private, which isn't super optimal because it makes it tricky to document with Sphinx and that it breaks existing code that depends on it.

Discussion Points

  1. Is it possible to whitelist methods that we don't want to be registered as routes? I would think that we would denote routes with the route decorator, but it appears that the ship has sailed on that design decision.
  2. Should we automatically exclude static methods from being registered as routes?

Should support route generation configuration for dashifying method names

Hey, thanks for taking this over. I love this lib.

Wondering if there is a way to change how the routes are generated from function names.

class TestView(FlaskView):
  def some_route(self):
    pass

The above will take some_route and turn it into test/someroute. In my stuff i moved to hyphens because some long names get hard to read. Is there a way to change it to test/some-route, other than a explicit @route decorator? Some kind of default config to always change underscores to hyphens.

@route('/view/file/<int:file_id>', methods=['GET']) generates error

If I remove 'int:' from the route string, it works as expected, but I want to specify parameter types as the same way flask's own route() does.
Doesn't flask-classful support argument type such as int:file_id? Or does it provide any other way to specify parameter types?

Sungsoo Kim

Traceback (most recent call last):
  File "manage.py", line 62, in <module>
    manager.run()
  File "/Users/sungsoo/.pyenv/versions/3.5.2/envs/cms/lib/python3.5/site-packages/flask_script/__init__.py", line 412, in run
    result = self.handle(sys.argv[0], sys.argv[1:])
  File "/Users/sungsoo/.pyenv/versions/3.5.2/envs/cms/lib/python3.5/site-packages/flask_script/__init__.py", line 383, in handle
    res = handle(*args, **config)
  File "/Users/sungsoo/.pyenv/versions/3.5.2/envs/cms/lib/python3.5/site-packages/flask_script/commands.py", line 216, in __call__
    return self.run(*args, **kwargs)
  File "manage.py", line 30, in list_routes
    url = url_for(rule.endpoint, **options)
  File "/Users/sungsoo/.pyenv/versions/3.5.2/envs/cms/lib/python3.5/site-packages/flask/helpers.py", line 323, in url_for
    force_external=external)
  File "/Users/sungsoo/.pyenv/versions/3.5.2/envs/cms/lib/python3.5/site-packages/werkzeug/routing.py", line 1756, in build
    rv = self._partial_build(endpoint, values, method, append_unknown)
  File "/Users/sungsoo/.pyenv/versions/3.5.2/envs/cms/lib/python3.5/site-packages/werkzeug/routing.py", line 1671, in _partial_build
    append_unknown)
  File "/Users/sungsoo/.pyenv/versions/3.5.2/envs/cms/lib/python3.5/site-packages/werkzeug/routing.py", line 1679, in _partial_build
    rv = rule.build(values, append_unknown)
  File "/Users/sungsoo/.pyenv/versions/3.5.2/envs/cms/lib/python3.5/site-packages/werkzeug/routing.py", line 798, in build
    add(self._converters[data].to_url(values[data]))
  File "/Users/sungsoo/.pyenv/versions/3.5.2/envs/cms/lib/python3.5/site-packages/werkzeug/routing.py", line 1016, in to_url
    value = self.num_convert(value)
ValueError: invalid literal for int() with base 10: '[queue_id]'

Special methods should work with Python 3.5 type hints

This works fine in Python 3.5:

class AwesomeView(FlaskView):

    def patch(self, id): 
        return"something" }

However if I want to use Python Type Hints, I have to manually add a @route decorator:

class AwesomeView(FlaskView):

    @route('/<id>', methods=['PATCH'])
    def patch(self, id: str) -> dict: 
        return"something" }

If I omit the decorator, then Flask-Classful triggers a ValueError with the following stack trace:

  File "/(...)/api/resources/posts.py", line 121, in <module>
    AwesomeView.register(app)
  File "/(...)/virtualenv/lib/python3.5/site-packages/flask_classful.py", line 134, in register
    rule = cls.build_rule("/", value)
  File "/(...)/virtualenv/lib/python3.5/site-packages/flask_classful.py", line 290, in build_rule
    argspec = get_true_argspec(method)
  File "/(...)/virtualenv/lib/python3.5/site-packages/flask_classful.py", line 360, in get_true_argspec
    argspec = inspect.getargspec(method)
  File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/inspect.py", line 1045, in getargspec
    raise ValueError("Function has keyword-only arguments or annotations"
ValueError: Function has keyword-only arguments or annotations, use getfullargspec() API which can support them

should fix docs publishing

errors should be fixed:

Copying files from '_build/html/.' to '_deploy/develop'
Deploying on github pages now...
[gh-pages 4bd056b] docs updated at Tue Sep 12 02:22:31 UTC 2017
 26 files changed, 11332 insertions(+), 239 deletions(-)
 create mode 100644 develop/_sources/index.rst.txt
 create mode 100644 develop/_sources/release.rst.txt
 rewrite develop/_static/comment-bright.png (99%)
 rewrite develop/_static/comment-close.png (99%)
 rewrite develop/_static/comment.png (99%)
 create mode 100644 develop/_static/jquery-3.1.0.js
 rewrite develop/_static/jquery.js (98%)
 rewrite develop/searchindex.js (95%)
remote: Invalid username or password.
fatal: Authentication failed for 'https://[secure]@github.com/teracyhq/flask-classful.git/'
make: *** [deploy_gh_pages] Error 128

from: https://travis-ci.org/teracyhq/flask-classful/jobs/274433983

not routing methods on base views

Hi, I have a 'BaseView' that extends FlaskView -- I want methods on this class to be ignored like they are for FlaskView -- is there a preferable way to implement this?

Regarding Flask-Classful to create singleton instance

from Sungsoo Kim

"
Dear Hoat Le,

I would like to appreciate your great work for Flask-Classful. It is very very helpful for my flask project.

While I look-up the source code of Flask-Classful, I have a question why Flask-Classful does not create singleton instance. Actually it creates instances for every methods while making routing rules, I think it makes some overhead and prevent each method from sharing instance variables.

Currently In order to share instance variables among FlaskView's methods, we should use class variables instead of instance variables.

Do you have any reason or intention not to create singleton instance of FlaskView?"

decorators that returns a value and flask classful

Hello

is there a way to support this?

I have the following class that uses customized decorators token_req and webargs's use_kwargs:

class AdView(FlaskView): 

    @token_req
    @use_kwargs(ad_schema.fields)
    def post(self, current_user, kwargs):
        print(**kwargs)
        return construct.post(model=Ad, schema=ad_schema, data=kwargs, current_user=current_user)

The route I want is /ad and the method is post, but because token_req returns the current user and use_kwargs returns the data entered, the url keeps showing 404 UNLESS I entered another two values like this:
/ads/3/fg. So how to support such a system?

Be able to provide arguments and a constructor

Hi,

First of all, many thanks for mantaining this project. I would like to know if this feature is currently supported. Imagine I have the following:

class ClassAView(FlaskView):
def init(self, pagename):
self.pagename = pagename

def index():
return 'Welcome to ' + self.pagename

Now, I would like to be able to instantiate an object of class ClassAView, register the Flask app to it, and give it a name as an argument to its constructor:

app = Flask(name)
instanceA = ClassAView('my page')
instanceA.register(app, route_base='/')
app.run()

I face some errors when doing something like this, so I tried to instantiate the object with an empty constructor, and then trying to define a setter method in order to provide "pagename". However, pagename is not stored and not displayed when requesting the index.

If not supported, I think it would be really nice to be able to interact with the REST facade with setter methods, or a constructor admitting arguments.

Many thanks for your help!

base_args should not be overriden when route_base is set

Hi, I was trying to combine flask-classful with webargs to make my API, this is an example code of how I did it, based on the quotes example in the docs:

from flask import Flask
from flask_classful import FlaskView
from webargs.flaskparser import use_args
from webargs import fields

# we'll make a list to hold some quotes for our app
quotes = [
    "A noble spirit embiggens the smallest man! ~ Jebediah Springfield",
    "If there is a way to do it better... find it. ~ Thomas Edison",
    "No one knows what he can do till he tries. ~ Publilius Syrus"
]

app = Flask(__name__)
app.config['DEBUG'] = True

put_args = {
    "text": fields.Str(required=True)
}

class QuotesView(FlaskView):
    base_args = ['args']
    def index(self):
        return "<br>".join(quotes)

    def get(self, id):
        id = int(id)
        if id < len(quotes) - 1:
            return quotes[id]
        else:
            return "Not Found", 404

    @use_args(put_args)
    def put(self, args, id):
        id = int(id)
        if id >= len(quotes) - 1:
            return "Not Found", 404
        quotes[id] = args['text']
        return quotes[id]

QuotesView.register(app)

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

The interesting part of this is the use of the @use_args decorator, that adds an argument args to the put function when called. To avoid having a /quotes/<args>/<id>/ URL (it should be /quotes/<id>/) i set the base_args class attribute to ['args'] so that parameter is ignored from the URL. (BTW this isn't documented, i had to manually look the code to understand it). Until now everything works as expected.

The problem comes when I want to set the route_base atribute so it isn't automatically calculated from the class name:

# ...

class UglyNameClass(FlaskView):
    base_args = ['args']
    route_base = 'quotes'
    # ...
    @use_args(put_args)
    def put(self, args, id):
        id = int(id)
        if id >= len(quotes) - 1:
            return "Not Found", 404
        quotes[id] = args['text']
        return quotes[id]

UglyNameClass.register(app)

This should be routed to /quotes/<id>/ as the previous example, but it gets routed as /quotes/<args>/<id>/, ignoring the base_args parameter I set.

Digging into the flask-restful code I saw that in get_route_base() the base_args is overriden when route_base exist:

    @classmethod
    def get_route_base(cls):
        """Returns the route base to use for the current class."""

        if cls.route_base is not None:
            route_base = cls.route_base
            base_rule = parse_rule(route_base)
            cls.base_args = [r[2] for r in base_rule]  # THE PROBLEM IS HERE
        else:
            route_base = cls.default_route_base()

        return route_base.strip("/")

I'm not sure why it overrides the value, but I think that it would be good to append to base_args instead of overriding it to support this use case.

It would be great to fix it to I could use views using webargs with a custom route_base

docs: type hint support could be mentioned more prominently

(spoiler: this is already a feature, I just didn't read far enough into the docs)


From the docs:

Note

One important thing to note, is that FlaskView does not type your parameters, so if you want or need them you’ll need to define the route yourself using the @route decorator.

It would be very neat to be able to do something like

class AnotherView(FlaskView):
    route_base = "home"

    def this_view(self, arg1: int, arg2: str):
        return "Args: %s, %s" % (arg1, arg2,)

and end up with a route like /home/this_view/<int:arg1>/<string:arg2> automatically, without having to do the @route decorator by hand.

Possible problems

Flask understands these types ("converters"):

  • string: accepts any text without a slash (the default)
  • int: accepts integers
  • float: like int but for floating point values
  • path: like the default but also accepts slashes
  • any: matches one of the items provided
  • uuid: accepts UUID strings

Of these, int and float will work as-is as Python type hints, str can be interpreted as string, and typing.Any as any.

The correct hint for path and uuid probably depends on what Flask passes them as – if Flask just passes them both as strings, then defining something like flask_classful.path and flask_classful.uuid (using typing.NewType) to be used as type hints is probably the best approach. OTOH, if Flask actually passes a uuid.UUID and/or pathlib.Path/os.PathLike, then it might be better to use those?

working app example with flask-classful.

its hard to implement the post function without running app example.
why post function should required view function? when I just have post with redirect in flask route decorator and work perfectly. please improve the documentation for flask newbie like. :(

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.