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

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. :)

Related

Fetching a mobile or desktop template using django middleware [duplicate]

I want to write custom template loader for my Django app which looks for a specific folder based on a key that is part of the request.
Let me get into more details to be clear. Assume that I will be getting a key on every request(which I populate using a middleware).
Example: request.key could be 'india' or 'usa' or 'uk'.
I want my template loader to look for the template "templates/<key>/<template.html>". So when I say {% include "home.html" %}, I want the template loader to load "templates/india/home.html" or "templates/usa/home.html" or "templates/uk/home.html" based on the request.
Is there a way to pass the request object to a custom template loader?
I've been searching for the same solution and, after a couple days of searching, decided to use threading.local(). Simply make the request object global for the duration of the HTTP request processing! Commence rotten tomato throwing from the gallery.
Let me explain:
As of Django 1.8 (according to the development version docs) the "dirs" argument for all template finding functions will be deprecated. (ref)
This means that there are no arguments passed into a custom template loader other than the template name being requested and the list of template directories. If you want to access paramters in the request URL (or even the session information) you'll have to "reach out" into some other storage mechanism.
import threading
_local = threading.local()
class CustomMiddleware:
def process_request(self, request):
_local.request = request
def load_template_source(template_name, template_dirs=None):
if _local.request:
# Get the request URL and work your magic here!
pass
In my case it wasn't the request object (directly) I was after but rather what site (I'm developing a SaaS solution) the template should be rendered for.
To find the template to render Django uses the get_template method which only gets the template_name and optional dirs argument. So you cannot really pass the request there.
However, if you customize your render_to_response function to pass along a dirs argument you should be able to do it.
For example (assuming you are using a RequestContext as most people would):
from django import shortcuts
from django.conf import settings
def render_to_response(template_name, dictionary=None, context_instance=None, content_type=None, dirs):
assert context_instance, 'This method requires a `RequestContext` instance to function'
if not dirs:
dirs = []
dirs.append(os.path.join(settings.BASE_TEMPLATE_DIR, context_instance['request'].key)
return shortcuts.render_to_response(template_name, dictionary, context_instance, content_type, dirs)

How to get the name of the Flask blueprint inside a template?

I have a site built with Flask. It has several sections, each with a dedicated blueprint. The templates in each blueprint extend a base template, which has the basic layout for each page, including a navigation bar with tabs for each section.
I'd like to have the base template highlight the current tab, so it needs to know which blueprint's view is handling the request.
One way I came up with to do this is to add a before_request handler to each blueprint and store the name in g:
bp = Blueprint('blog', __name__, url_prefix='/blog')
#bp.before_request
def set_bp_name():
g.section = 'blog'
But Flask must know which blueprint is handling a request (if any) and the blueprint, of course, knows its own name. Is there a way for the template to fetch the current blueprint's name that doesn't require modifying each blueprint?
Yes. Quite simply: request.blueprint.
The request object is one of a few (along with g) that Flask makes available to all templates. It contains the blueprint property, which is the name of the blueprint handling the current request.

How to extending config in view

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.

How to add flask-admin to my existing flask

For the past two days I've been trying to intergrate flask-admin to my already existing flask application. But the problem is that I keep getting the same error:
builtins.AssertionError
AssertionError: A name collision occurred between blueprints <flask.blueprints.Blueprint object at 0x000001D8F121B2B0> and <flask.blueprints.Blueprint object at 0x000001D8ECD95A90>. Both share the same name "admin". Blueprints that are created on the fly need unique names.
and that error comes from this block of lines:
Main flask application:
app.route("/admin")
def admin():
if not session.get('logged_in'):
return redirect(url_for('login'))
return adminScreen.adminPage()
admin.py
def adminPage():
admin=Admin(app)
admin.add_view(ModelView(User, db.session))
admin.add_view(ModelView(Role, db.session))
admin.add_view(ModelView(PointOfSale, db.session))
return admin
And what I want to do is to manage the users that I already have in my database by using the functions that flask-admin provide.
So my question is; is there a simple way to route flask-admin to my pre-existing flask application?
P.S I already know that there is this post from May of 2018, but I have no idea how to implement the solution that was provided.
You don't have to create an app.route("/admin") yourself. That is provided by the built-in blueprint from flask-admin.
In order to use blueprints correctly you should update your app to use app factory instead global variable. Otherwise you cannot have multiple instances of the application.
In existing project it may require some work to do but it's worth it.
Example factory may looki like this:
def create_app(config_filename):
app = Flask(__name__)
app.config.from_pyfile(config_filename)
from yourapplication.model import db
db.init_app(app)
from yourapplication.views.admin import admin
from yourapplication.views.frontend import frontend
app.register_blueprint(admin)
app.register_blueprint(frontend)
return app
You can find more information here:
http://flask.pocoo.org/docs/1.0/patterns/appfactories/

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