briancappello / flask-unchained Goto Github PK
View Code? Open in Web Editor NEWThe quickest and easiest way to build large web apps and APIs with Flask
Home Page: https://flask-unchained.readthedocs.io
License: MIT License
The quickest and easiest way to build large web apps and APIs with Flask
Home Page: https://flask-unchained.readthedocs.io
License: MIT License
Looks like BundleConfig
was introduced on 16 October 2018, but release 0.6.6 was cut on 9 October 2018, which means the latest release doesn't have this class defined.
The missing class definition means that flask-unchained-react-spa
doesn't work out of the box.
Cutting a new release would presumably fix: briancappello/flask-unchained-react-spa#3
When running backend in a docker container using backend as its dns,
a frontend proxying to the backend hosting at example.com,
gitlab url conains backend:5000 which should be example.com:
&redirect_uri=https%3A%2F%2Fbackend%3A5000%2Fauth%2Fauthorized%2Fgitlab&scope=openid+read_user
The config.py contains this for oauth:
OAUTH_REMOTE_APP_GITLAB = dict(
consumer_key=os.getenv('OAUTH_GITLAB_CONSUMER_KEY', ''),
consumer_secret=os.getenv('OAUTH_GITLAB_CONSUMER_SECRET', ''),
base_url='https://gitlab.com/api/v4/user',
access_token_url='https://gitlab.com/oauth/token',
access_token_method='POST',
authorize_url='https://gitlab.com/oauth/authorize',
request_token_url=None,
request_token_params={'scope': 'openid read_user'},
)
Adding
SERVER_NAME='example.com' breaks
The problem is url_for in bundles.oauth.views.OAuthController.login,
which creates http://backend:5000.
return provider.authorize(callback=url_for(
'o_auth_controller.authorized', remote_app=remote_app,
_external=True, _scheme='https'))
Is there a way to customize the generated url_for.
Setting SERVER_NAME='example.com' breaks, frontend be able to reach the server using backend:5000.
pip install git+https://github.com/briancappello/flask-unchained
flask new project testproj # y to all
cd testproj/
pip install -r requirements-dev.txt
pip install marshmallow-sqlalchemy==0.14.1
flask run
Bundles Config:
BUNDLES = [
'flask_unchained.bundles.api',
'flask_unchained.bundles.mail',
'flask_unchained.bundles.celery', # move before mail to send emails synchronously
'flask_unchained.bundles.security',
'flask_unchained.bundles.session',
'flask_unchained.bundles.sqlalchemy',
'flask_unchained.bundles.webpack',
'app', # your app bundle *must* be last
]
Opening localhost:5000 in browser throws following:
flask run
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 117-607-828
127.0.0.1 - - [18/Nov/2018 10:17:36] "GET / HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 1808, in full_dispatch_request
self.try_trigger_before_first_request_functions()
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 1855, in try_trigger_before_first_request_functions
func()
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_unchained/bundles/api/__init__.py", line 62, in register_model_resources
api.register_model_resource(resource)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_unchained/bundles/api/extensions/api.py", line 123, in register_model_resource
route = unchained.controller_bundle.controller_endpoints[key]
KeyError: 'UserResource.patch'
First of, I just want to say thank you for making this package. This is exactly what I need for a project I'm doing.
Anyways, the issue at hand:
The login and logout endpoints specified in the Admin bundle config seems to point to an endpoint in the Security bundle which doesn't exist in the current commit.
i.e. ADMIN_LOGOUT_ENDPOINT = "security.logout"
My workaround is just to set this variable in my project config to ADMIN_LOGOUT_ENDPOINT = "security_controller.logout"
I think a better solution would be to either set the config variable in the Admin bundle itself to "security_controller.<endpoint>"
, or edit the references in the Security bundle to "security.<endpoint>"
. I don't have a personal opinion on which option is better. Maybe there's even a better solution.
I can make a PR either way, if needed.
Attached is a screenshot of the werkzeug routing error I encounter when trying to access /admin/.
With and without
class Config(AppBundleConfig):
SQLALCHEMY_DATABASE_URI = 'sqlite:///db/flaskr.sqlite'
in file app/config.py
127.0.0.1 - - [18/Nov/2018 16:35:46] "GET / HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 1816, in full_dispatch_request
return self.finalize_request(rv)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 1833, in finalize_request
response = self.process_response(response)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask/app.py", line 2114, in process_response
self.session_interface.save_session(self, ctx.session, response)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_session/sessions.py", line 535, in save_session
session_id=store_id).first()
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2895, in first
ret = list(self[0:1])
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2687, in __getitem__
return list(res)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2995, in __iter__
return self._execute_and_instances(context)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 3018, in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 948, in execute
return meth(self, multiparams, params)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 269, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1060, in _execute_clauseelement
compiled_sql, distilled_params
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1200, in _execute_context
context)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1413, in _handle_dbapi_exception
exc_info
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 265, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 248, in reraise
raise value.with_traceback(tb)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1193, in _execute_context
context)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 509, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: flask_sessions [SQL: 'SELECT flask_sessions.id AS flask_sessions_id, flask_sessions.session_id AS flask_sessions_session_id, flask_sessions.data AS flask_sessions_data, flask_sessions.expiry AS flask_sessions_expiry, flask_sessions.created_at AS flask_sessions_created_at, flask_sessions.updated_at AS flask_sessions_updated_at \nFROM flask_sessions \nWHERE flask_sessions.session_id = ?\n LIMIT ? OFFSET ?'] [parameters: ('session:31d9ead7-138a-4d50-be58-2f2c8d54a8f2', 1, 0)] (Background on this error at: http://sqlalche.me/e/e3q8)
I tried flask db init, but didn't help.
db/flaskr.sqlite is generated but empty.
Hi, a single route annotation works, tried both,
but stacking route annotations, only first works.
@route('/list/<string:project>/', defaults={'req_path': ''})
@route('/list/<string:project>/<path:req_path>')
def image_listing(self, project, req_path):
...
Solution: You must install alembic
from master for now:
pip install git+https://github.com/sqlalchemy/alembic.git#egg=alembic
(see sqlalchemy/alembic#548)
Many upstream projects are converging to black
, and we did so at my former employer as well. It's extremely opinionated (and I found it somewhat ugly at first sight), but on the other hand, it:
Consider using it in this project too?
I'd even go so far as to vote for a single, minor customization of changing the default line length back down to 80 columns (instead of its default of 88), but feel free to ignore that suggestion if it's not your cup of tea.
It looks like there are serializers for https://github.com/briancappello/flask-unchained/blob/master/flask_unchained/_code_templates/project/app/models/user.py needed, which is missing.
pip install git+https://github.com/briancappello/flask-unchained
flask new project testproj # y to all
cd testproj/
pip install -r requirements-dev.txt
flask run
Traceback (most recent call last):
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_unchained/bundles/api/hooks/register_model_resources_hook.py", line 30, in attach_serializers_to_resource_cls
serializer_cls = self.bundle.serializers_by_model[model_name]
KeyError: 'User'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_unchained/cli.py", line 56, in cli_create_app
return AppFactory.create_app(env)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_unchained/app_factory.py", line 75, in create_app
unchained.init_app(app, env, bundles, _config_overrides=_config_overrides)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_unchained/unchained.py", line 107, in init_app
run_hooks_hook.run_hook(app, bundles, _config_overrides=_config_overrides)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_unchained/hooks/run_hooks_hook.py", line 34, in run_hook
hook.run_hook(app, bundles)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_unchained/app_factory_hook.py", line 98, in run_hook
self.process_objects(app, self.collect_from_bundles(bundles))
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_unchained/bundles/api/hooks/register_model_resources_hook.py", line 25, in process_objects
self.attach_serializers_to_resource_cls(model_name, resource_cls)
File "/home/chriamue/temp/venv/lib/python3.6/site-packages/flask_unchained/bundles/api/hooks/register_model_resources_hook.py", line 32, in attach_serializers_to_resource_cls
raise KeyError(f'No serializer found for the {model_name} model')
KeyError: 'No serializer found for the User model'
In my experience, I have found it easier to both work with and teach pipenv over venv, would you be open to switching to that? I am looking to implement dotenv but don't want to double up on work if I can help it.
Let's say you had an API endpoint somewhere. You want to keep some logic out of the view, but you also need to have some method/functionality. For example's sake, it's some generic thing like reversing a list. Some projects might be tempted to make a utils
package and start dumping code into that. I try to delay that as much as I can because it turns out to be a junk drawer. Since Flask-Unchained is slightly opinionated (not pejorative - I prefer this in a framework), where would you put plain old python classes?
Answering my own question, here are some thoughts or suggestions:
helpers/
- It's too close to utils. Everything should be helping. Eh. I usually have formatters for views or something near something else for thismodels/
- Is sqlalchemy. Reversing a list doesn't touch the database. The name is very close and a model doesn't have to touch the database. In this case, a list doesn't really contain data. A User / Person / Employee / Product / Comment is a model.lib/
- Is more of a C/C++ convention, I don't hate it though.services/
- I'd consider this hitting the network. A network service. The term is overused. FormObjects are sometimes called services.utils/
- The default. Turns into a junk drawer.list/
- Naming it after the business case, the domain is not how Flask-Unchained is organized. It's organized by technical types.decorators/
- I like this for views, same as FormObjects.presenters/
- Now we're just doing synonyms here. I like this for this example because I'm probably reversing a list for a table maybe? My made up example isn't real.Maybe the hangup on presents answers the question. I should think more about why I'm reversing a list. If it's on the backend to the database, put it in there. If it's on the backend talking to a service, put it in services. If it's going to the frontend for the view, put it in helpers. If it is so general that it is used by everything, put it in utils?
Naming stuff is hard.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.