How to extending config in view - python

I have an external package that installs (pip install) in venv with my pyramid project. And I want extending config in the view. The client.include.my_pack have this function adding router:
def includeme(config):
config.add_route('my_url_view', url)
This package should be used in multiple projects and I want to connect it in only one place in the project.
I try connect it:
from pyramid.view import view_config
from pyramid.config import Configurator
config = Configurator()
config.include('client.include.my_pack')
config.scan()
#view_config(route_name='my_url_view', request_method='POST', renderer='json')
def home(request):
pack = request.validated['expected']
return pack
But this code raise exceptions:
pyramid.exceptions.ConfigurationExecutionError: <class 'pyramid.exceptions.ConfigurationError'>: No route named expected found for view registration.
How can I add route in the display instead of __ init __.py project file?

The exception is "No route named expected found for view registration". Your examples talk about a route named "my_url_view", not "expected". I suspect you have another view referencing a route that is not defined? I don't see anything wrong with your pasted code.

Related

Flask - How to properly set global values

I'm currently working on a web app where I'm using Flask and the Flask-User extension to handle authorization. At the moment I have something like this:
#application.route('/dummy')
#roles_required('Admin')
#login_required
def dummy():
in my views.py file and something like this:
{% if current_user.is_authenticated and current_user.has_roles('Admin') %}
in my templates.
Now, there's been a few times where I've changed my mind in terms of role names and then had to search through the whole project to find and replace those usages. I wanted to define something like a ADMIN_ROLE global that can be accessed inside my views.py or any templates. I'd then just change a config file whenever I wanted to change a role's name.
I tried using my config.py setting ADMIN_ROLE = "Admin" and writing #roles_required(current_app.config['ADMIN_ROLE']) but that gives me the following error:
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in a way. To solve
this set up an application context with app.app_context(). See the
documentation for more information.
so that should be wrong. What would be the most correct way to accomplish what I'm trying?
As it says, you can only access config from within the app context. Normally, you do this:
with current_app.app_context():
admin_role = current_app.config['ADMIN_ROLE']
Because you're doing this in a decorator, I don't believe there's anyway to do that. I would suggest just using a separate module. Now, it doesn't appear that you can use python import statements in jinja, so we'll still use app.config for that. Basically we'll create a module with the desired roles and then import that into the config file and your routes file.
roles.py
ADMIN = "Admin"
USER = "User"
config.py
from roles import ADMIN, USER
ADMIN_ROLE = ADMIN
USER_ROLE = USER
routes.py
from roles import ADMIN, USER
#application.route('/dummy')
#roles_required(ADMIN)
#login_required
def dummy():
views.py
{% if current_user.is_authenticated and current_user.has_roles(app.config['ADMIN_ROLE']) %}

route endpoint conflicts when generating sphinx doc for flask restful api

I'm trying to build documentation for a Flask webapp that includes a REST-like API built into it. I'm using sphinx, specifically the httpdomain extension from sphinxcontrib, using the autohttp.flask module to auto-generate my Flask docs, and the autohttp.qrefflask module to auto-generate a quick reference table to go along with it. However, when I try to build my sphinx docs (make html), I'm running into the error of conflicting route endpoints
Exception occurred:
File "/Users/../anaconda2/lib/python2.7/site-packages/flask/app.py", line 1051, in add_url_rule
'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: api.View1:add_config
I only really care about generating documentation for my API and none of the Flask web routes, so I've restricted my sphinx documentation to only build the api blueprints. Here is my sphinx api.rst
.. qrefflask:: myapp.web:create_app(debug=True)
:undoc-static:
:endpoints:
:blueprints: api
:order: path
.. autoflask:: myapp.web:create_app(debug=True)
:undoc-static:
:endpoints:
:blueprints: api
:order: path
My Flask app and Blueprint layout is as follows:
myapp/
api/
__init__.py (api blueprint defined here)
view1.py
view2.py
view3.py
web/
__init__.py (main Flask app created here via create_app)
I'm wondering if it's a problem with how I'm registering the blueprint, and that sphinx somehow is registering it twice, but I don't understand it.
My api.__init__.py basically has my Blueprint definition and a few custom error handlers:
from flask import Blueprint, jsonify
theapi = Blueprint("api", __name__, url_prefix='/myapp/api')
#theapi.errorhandler(500)
def internal_server_error(err):
messages = {'error': 'internal_server_error',
'message': err.description,
'traceback': get_traceback(asstring=True)}
return jsonify({
'api_error': messages,
}), 500
while my main Flask app creation, web.__init__.py just imports this and registers everything:
def create_app(debug=False, local=False):
from myapp.api import theapi as api
from myapp.api.view1 import View1
...
app = Flask(__name__, static_url_path='/myapp/static')
...
View1.register(api)
app.register_blueprint(api)
return app
If I move the api blueprint definition and error_handlers into the main app creation, everything works fine. But then that breaks the modularity of it. I'd like to keep my api stuff inside the api module. Also, if remove either the main autoflask or qrefflask generation, and only use one, everything works fine. But I'd really like to have the quick reference guide. The code itself runs fine, but the damn documentation is failing to build. Does anyone have any suggestions?

Flask per-blueprint error pages

I have a flask application that looks somewhat like this:
app.py
blueprints/
www.py
shop.py
app.py imports blueprint objects from each of the files in the blueprints directory and registers them with the Flask object in app.py with an appropriate subdomain (also imported from the file). Each blueprint registers error handlers, however these are only invoked when a view manually calls abort(), not by general errors (i.e. calling a non existent URL on the subdomain managed by shop.py invokes the error handler on app.py instead.)
Is there any way to force flask to pass errors to the blueprint that is handling the subdomain in which that error is occurring?
Flask's documentation says that this is not possible for 404s and 500s. If you need this functionality you might be able to use a wildcard route in your blueprint to handle 404s:
#a_blueprint.route("<path:invalid_path>")
def missing_resource(invalid_path):
return "There isn't anything at " + invalid_path, 404
You can use current_app and put it in the blueprints. Something like:
shop.py
from flask import current_app
#current_app.errorhandler(404)
def page_not_found(e):
return redirect(url_for('shop.index'))

How do you wrap the view of a 3rd-party Django app

How do you wrap the view of a 3rd-party app (let's call the view to wrap "view2wrap" and the app "3rd_party_app") so you can do some custom things before the app does its thing?
I've set urls.py to capture the correct url:
url( r'^foo/bar/$', view_wrapper, name='my_wrapper'),
I've created my custom view:
from 3rd_party_app.views import view2wrap
def view_wrapper(request, *args, **kwargs):
# Do some cool custom stuff
return view2wrap(request, *args, **kwargs)
When I try this, I get the error "No module named 3rd_party_app.views". Why?
The third party application is not in your python path.
Is the 3rd Party App listed in INSTALLED_APPS in your settings.py?
Try placing the 3rd party package folder within your project folder. :)

Excluding a Django app from being localized using a middleware

I need to localize a django project, but keep one of the applications (the blog) English only.
I wrote this middleware in order to achieve this:
from django.conf import settings
from django.core.urlresolvers import resolve
class DelocalizeMiddleware:
def process_request(self, request):
current_app_name = __name__.split('.')[-2]
match = resolve(request.path)
if match.app_name == current_app_name:
request.LANGUAGE_CODE = settings.LANGUAGE_CODE
Problem is, it assumes the middleware lies directly in the application module (e.g. blog/middleware.py) for retrieving the app name. Other projects might have the middleware in blog/middleware/delocalize.py or something else altogether.
What's the best way to retrieve the name of the currently running app?
You can use Django's resolve function to get the current app name.
https://docs.djangoproject.com/en/dev/topics/http/urls/#resolve

Categories