django href url with parameter throwing error - python

I have the following setup for a simple href download page:
urls.py
urlpatterns = [
url(r'^kpis/$', InternalKPIView.as_view(), name='internal_kpis'),
url(r'^tenants/$', TenantListView.as_view(), name='tenant-list'),
url(r'^tenants/(?P<pk>[0-9]+)/$', TenantStatsView.as_view(), name='tenant-stats'),
url(r'^fileformaterror/$', FileFormatErrorView.as_view(), name='file-format-error'),
url(r'^fileformaterror/download/(?P<s3_key>.*)$', FileFormatErrorDownloadView.as_view(), name='file-format-error-download'),
]
template.html:
Download
views.py:
class FileFormatErrorDownloadView(View):
def get(self, request, s3_key):
pass
But when executing I get the following error:
django.urls.exceptions.NoReverseMatch: Reverse for 'file-format-error-download' not found. 'file-format-error-download' is not a valid view function or pattern name.
Tree output of the related files:
$ tree -I "*.pyc|__pycache__"
.
├── apps.py
├── __init__.py
├── migrations
│   └── __init__.py
├── templates
│   └── backoffice
│   ├── file_format_error.html
│   └── internal_kpis.html
├── urls.py
└── views.py
3 directories, 7 files

From what you've provided it seems like the urls.py you are showing belongs to one of the applications within the project. My guess is that URLs of that application are either not included properly or included with a namespace.

why not use django2.0+? then code may as below:
urls.py
path('fileformaterror/download/<s3_key>/', FileFormatErrorDownloadView.as_view(), name='file-format-error-download')
template.html
Download
views.py
from django.shortcuts import HttpResponse
class FileFormatErrorDownloadView(View):
def get(self, request, s3_key):
return HttpResponse('success')

Related

How do I set up my Django urlpatterns within my app (not project)

Let's say I've got the classic "School" app within my Django project. My school/models.py contains models for both student and course. All my project files live within a directory I named config.
How do I write an include statement(s) within config/urls.py that references two separate endpoints within school/urls.py? And then what do I put in schools/urls.py?
For example, if I were trying to define an endpoint just for students, in config/urls.py I would do something like this:
from django.urls import path, include
urlpatterns = [
...
path("students/", include("school.urls"), name="students"),
...
]
And then in school/urls.py I would do something like this:
from django.urls import path
from peakbagger.views import StudentCreateView, StudentDetailView, StudentListView, StudentUpdateView, StudentDeleteView
urlpatterns = [
# ...
path("", StudentListView.as_view(), name="student-list"),
path("add/", StudentCreateView.as_view(), name="student-add"),
path("<int:pk>/", StudentDetailView.as_view(), name="student-detail"),
path("<int:pk>/update/", StudentUpdateView.as_view(), name="student-update"),
path("<int:pk>/delete/", StudentDeleteView.as_view(), name="student-delete"),
]
But how do I do I add another urlpattern to config/urls.py along the lines of something like this? The include statement needs some additional info/parameters, no?
from django.urls import path, include
urlpatterns = [
...
path("students/", include("school.urls"), name="students"),
path("courses/", include("school.urls"), name="courses"),
...
]
And then what happens inside of school/urls.py?
I'm open to suggestions, and definitely am a neophyte when it comes to the Django philosophy. Do I need an additional urls.py somewhere? I'd prefer not to put everything in config/urls.py and I'd prefer not to build a separate app for both students and courses.
I would rather create two (or more) urls.py files and then point them separately.
# directory structure
school/
├── admin.py
├── apps.py
├── __init__.py
├── migrations
│   └── __init__.py
├── models.py
├── tests.py
├── urls
│   ├── course.py
│   ├── __init__.py
│   └── student.py
└── views.py
# school/urls/course.py
from django.urls import path
from school.views import CourseListView
urlpatterns = [
path("", CourseListView.as_view(), name="course_list"),
# other URLs
]
# school/urls/student.py
from django.urls import path
from school.views import StudentListView
urlpatterns = [
path("", StudentListView.as_view(), name="student_list"),
# other URLs
]
# config/urls.py
from django.urls import include, path
urlpatterns = [
path("student/", include("school.urls.student")),
path("course/", include("school.urls.course")),
# other URLs
]
The best solution for you is to make separate urls directory inside your app
For example if you have school as app then
app
├── School
│ ├── views.py
│ └── models.py
| └── urls
| └── __init__.py
| └── urls.py
| └── school_urls.py
| └── course_urls.py
Now in your main project urls you can set this way
urlpatterns = [
...
path("", include("school.urls"), name="students"),
...
]
and in urls.py of your school urls folder you can do this way
urlpatterns = [
...
path("students/", include("school.urls.school_urls"), name="students"),
path("course/", include("school.urls.course_urls"), name="course"),
...
]
and you can do add course view in course url folder and another student view in student urls file

Organizing a Flask project

This is my first time creating a project using python and flask. I intend to use SQLAlchemy models along too. and this is a fairly bigger project. As of now, I have divided the project in 2 Blueprints : site and the api. After organizing the project, I am confused as to how can I connnect these models with the database and do I need to re-organize the structure as I am not fully aware of nature of flask.
so this is the directory structure of the dir app/ in my base repository:
`
.
├── Blueprints
│   ├── __init__.py
│   ├── __pycache__
│   │   └── __init__.cpython-36.pyc
│   ├── api
│   │   ├── __init__.py
│   │   ├── __pycache__
│   │   │   ├── __init__.cpython-36.pyc
│   │   │   └── routes.cpython-36.pyc
│   │   └── routes.py
│   ├── config.py
│   └── site
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   └── routes.cpython-36.pyc
│   ├── operations.py
│   ├── routes.py
│   ├── static
│   └── templates
│   ├── about.html
│   ├── contact.html
│   ├── home.html
│   ├── login.html
│   ├── services.html
│   └── stories.html
├── __main__.py
├── __pycache__
│   └── __main__.cpython-36.pyc
└── models
├── Attendance.py
├── Batch.py
├── Course.py
├── Module.py
├── Student.py
├── Test.py
└── __init__.py
`
Please ignore Pycache, as this is auto generated.
now I cannot figure out a way as to how to import and use these models in api and site, neither I can understand as to how am I supposed to fetch the db object created in /Blueprints/__init__.py to all the models.
I understand that this question is not upto the standards of stack overflow questions, BUT I personally feel that organizing a flask project is itself very confusing with each tutorial or forum I see, having their own perspectives of organizing it.
There's several ways to organize a project, but the __init__.py file contained inside the app/ folder is what links a lot of it together. Here's the contents of one of my project's __init__.py file:
from werkzeug.contrib.fixers import ProxyFix
from flask import Flask, session
from app.config import (PERMANENT_SESSION_LIFETIME_MS, Time_Before_Warning,
Min_Ping_Interval)
import datetime
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app)
# Setup the app with the config.py file
app.config.from_pyfile('config.py')
# Setup the logger
from app.logger_setup import logger, log_view
# Setup the database
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
#setup zipcode database
from pyzipcode import ZipCodeDatabase
zdb = ZipCodeDatabase()
# Setup the mail server
from flask.ext.mail import Mail
mail = Mail(app)
# Setup the debug toolbar
#from flask_debugtoolbar import DebugToolbarExtension
#app.config['DEBUG_TB_TEMPLATE_EDITOR_ENABLED'] = False
#app.config['DEBUG_TB_PROFILER_ENABLED'] = False
#toolbar = DebugToolbarExtension(app)
# Setup the password crypting
from flask.ext.bcrypt import Bcrypt
bcrypt = Bcrypt(app)
# Import the views
from app.views import (main, user, error, request, upload, dashboard, org,
msgs, notifications, download, reports,
direct_send,provider,utils)
app.register_blueprint(user.userbp)
app.register_blueprint(request.requestbp)
app.register_blueprint(upload.uploadbp)
app.register_blueprint(dashboard.dashboardbp)
app.register_blueprint(org.orgbp)
app.register_blueprint(msgs.msgbp)
app.register_blueprint(notifications.notificationsbp)
app.register_blueprint(download.downloadbp)
app.register_blueprint(reports.reportsbp)
app.register_blueprint(direct_send.directsendbp)
app.register_blueprint(provider.providerbp)
app.register_blueprint(utils.utilsbp)
# Setup the user login process
from flask.ext.login import LoginManager, current_user
from app.models import User, View
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'userbp.signin'
#login_manager.user_loader
def load_user(email):
return User.query.filter(User.email == email).first()
from flask.ext.principal import identity_loaded, RoleNeed, UserNeed
#identity_loaded.connect_via(app)
def on_identity_loaded(sender, identity):
# Set the identity user object
identity.user = current_user
# Add the UserNeed to the identity
if hasattr(current_user, 'id'):
identity.provides.add(UserNeed(current_user.id))
# Assuming the User model has a list of roles, update the
# identity with the roles that the user provides
if hasattr(current_user, 'roles'):
identity.provides.add(RoleNeed(current_user.roles.type))
from flask.ext.principal import Principal
# load the extension
principals = Principal(app)
# Create a permission with a single Need, in this case a RoleNeed.
#from app import admin
#app.before_request
def make_session_permanent():
session.permanent = True
lt = PERMANENT_SESSION_LIFETIME_MS / (60*1000)
app.permanent_session_lifetime = datetime.timedelta(minutes=lt)
#app.context_processor
def add_session_config():
"""
Add current_app.permanent_session_lifetime converted to milliseconds
to context.
"""
return {
'PERMANENT_SESSION_LIFETIME_MS': PERMANENT_SESSION_LIFETIME_MS,
'Time_Before_Warning': Time_Before_Warning,
'Min_Ping_Interval': Min_Ping_Interval,
}
And then inside one of the blueprints:
from flask import (Blueprint, render_template, redirect, url_for,
abort, flash, request)
from flask.ext.login import login_required, current_user
from app import app, models, db, log_view, config
from app.models import (Groups, Organizations, OrgHasOwner, UserHasGroups,
GroupHasOwner, User, Fax, FavoriteGroups)
from app.forms import org as org_forms
from app.toolbox import email, misc, s3, fax
from sqlalchemy.sql import func
from werkzeug import secure_filename
from uuid import uuid4
import datetime
import string
import os
# Create a user blueprint
orgbp = Blueprint('orgbp', __name__, url_prefix='/org')
#orgbp.route('/invite_user', methods=['GET','POST'])
#login_required
def invite_user():
[stuff goes here]

Proper way to include builds from react apps into Flask

I have a site developed entirely using flask. It uses a Blueprint called dashboards, which hosts some views to access different visualizations, i.e dashboards/<string: dashboard_name>
I store my dashboards with an id, a name and the group it belongs to, so users can only access the visualizations from the group they also belong to.
(This is my unexperienced approach to solve this problem, so I'm also open to suggestions of a better design pattern to achieve this.)
My project kinda looks like this
app
├── dashboards
│   ├── __init__.py
│   └── views.py
├── __init__.py
├── models
│   ├── dashboard.py
│   └── __init__.p
├── static
│   ├── css
│   │   ├── styles.css
│   └── js
│   └── scripts.js
└── templates
├── base.html
└── dashboards
   ├── cat.html
   ├── clock.html
   ├── index.html
   ├── private.html
   └── public.html
my views for the Dashboard blueprint
# app/dashboards/views.py
from ..models.dashboard import Dashboard
#dashboards.route('/<string:name>')
def view_dashboard(name):
# a dictionary with dashboards available to current_user
dashboards = get_dashboards()
for dashboard in dashboards.values():
for d in dashboard:
if name == d.name:
route = 'dashboards/{dashboard}.html'.format(dashboard = d.name)
return render_template(route, dashboard=d)
else:
return render_template('404.html'), 404
and for the Dashboard blueprint
# app/dashboards/__init__.py
from flask import Blueprint
dashboards = Blueprint('dashboards', __name__)
from . import views
finally, I use the create_app pattern
# app/__init__.py
# some imports happening here
def create_app(config_name):
app = Flask(__name__)
from .dashboards import dashboards as dashboards_blueprint
app.register_blueprint(dashboards_blueprint, url_prefix='/dashboards')
return app
One level above the app, there is a manage.py that calls the create_app method, passing some configuration attributes. I believe this is a common pattern in Flask. I also believe this is not relevant to my question.
Particularly, if one deploys a react app using the create-react-app package, i.e. using npm run build, the output is a folder /build that contains the static files necessary to run the app. This folder has, for instance the following structure
├── build
│   ├── asset-manifest.json
│   ├── favicon.ico
│   ├── index.html
│   ├── manifest.json
│   ├── service-worker.js
│   └── static
│   ├── css
│   │   ├── main.<some-hash-1>.css
│   │   └── main.<some-hash-1>.css.map
│   └── js
│   ├── main.<some-hash-2>.js
│   └── main.<some-hash-2>.js.map
other files here
Now if want to plug this react-app using Flask, what I do now is to move the files in /css and /js of /build to the /static folder inside /app, and rename index.html from /build into let's say 'react-dashboard.html' and move it to templates/dashboards.
This is a very dumb approach to make basic apps working, but I don't know where to place the other files from /build, and lest about a better design pattern.
From this README I get that I can tweak the blueprint definition and move my template and static folder inside app/dashboards, but I still don't know where other files as service-worker.js, and manifests and so on.
What is the proper way to "mount" my deployed react app on my Flask application? I understand that reorganizing files from /build is something not desired.
I've solved it tweaking the blueprint
bp = Blueprint(name='myblueprint',
import_name=__name__,
static_folder='static/myblueprint',
template_folder='templates',
static_url_path='/static', # this is what myblueprint.static will point to
url_prefix='/myblueprint',
subdomain=None,
url_defaults=None,
root_path=None)
With this, my static paths inside the blueprint will point to /myblueprint/static, and I will need to modify my create-react-app build folder.
replace calls to static in every *.css, *.js and .html in /build to /myblueprint/static
rearrange folders inside /build to match my blueprint static folder.
Move /build/static to /blueprint/static
Set my own jinja template in /blueprint/templates/index.html that calls these files. Make sure this file points to the static assets in /myblueprint/static and not to /build/static.
I've created a gulpfile that will automate this process,
var gulp = require('gulp');
var replace = require('gulp-replace');
var rename = require('gulp-rename');
// script to deploy react build into flask blueprint directory
// it replaces values and folder names
// README
// how to use this:
// in the react app, run npm run build
// copy the resulting /build folder in /myblueprint
// create a template of a template in /templates/base as index.default.html
// install gulp, gulp-replace, gulp-rename
// run gulp from /myblueprint
// replace routes inside css files
gulp.task('othertemplates', function(){
gulp.src(['./build/static/css/main.*.css'])
.pipe(replace('url(/static/media/', 'url(/myblueprint/static/media/'))
.pipe(gulp.dest('static/myblueprint/css/'));
});
// replace routes inside js files
gulp.task('jsthingtemplates', function(){
gulp.src(['./build/static/js/main.*.js'])
.pipe(replace('static/media/', 'myblueprint/static/media/'))
.pipe(gulp.dest('static/myblueprint/js/'));
});
// move other files
gulp.task('mediastuff', function(){
gulp.src(['./build/static/media/*'])
.pipe(gulp.dest('static/myblueprint/media/'));
gulp.src(['./build/asset-manifest.json'])
.pipe(gulp.dest('static/myblueprint/'));
});
// replace hashes in assets in the jinja template
gulp.task('jinjareplace', function(){
var fs = require('fs');
var assets = JSON.parse(fs.readFileSync('./build/asset-manifest.json'));
// extract hashes
let jsHashNew = assets['main.js'].match('[a-z0-9]{8}')
let cssHashNew = assets['main.css'].match('[a-z0-9]{8}')
gulp.src(['./templates/myblueprint/base/index.default.html'])
.pipe(replace('css/main.cssHash.css', `css/main.${cssHashNew}.css`))
.pipe(replace('js/main.jsHash.js', `js/main.${jsHashNew}.js`))
.pipe(rename('index.html'))
.pipe(gulp.dest('templates/myblueprint/'));
});
gulp.task('default', ['othertemplates', 'jsthingtemplates', 'mediastuff', 'jinjareplace'])
with this, you can run gulp from the same path as gulpfile.js and should have everything covered.

Flask teardown request in context of blueprint

I would like to access an sqlite3 database from a Flask application (without using Flask-SQLAlchemy, since I require fts4 functionality). I am using Flask blueprints, and I am not sure where to put the following functions (shamelessly copied from a response to this stackoverflow question):
def request_has_connection():
return hasattr(flask.g, 'dbconn')
def get_request_connection():
if not request_has_connection():
flask.g.dbconn = sqlite3.connect(DATABASE)
# Do something to make this connection transactional.
# I'm not familiar enough with SQLite to know what that is.
return flask.g.dbconn
#app.teardown_request
def close_db_connection(ex):
if request_has_connection():
conn = get_request_connection()
# Rollback
# Alternatively, you could automatically commit if ex is None
# and rollback otherwise, but I question the wisdom
# of automatically committing.
conn.close()
My file structure is:
app
├── __init__.py
├── main
│   ├── forms.py
│   ├── __init__.py
│   ├── views.py
├── models.py
├── static
└── templates
├── base.html
├── index.html
└── login.html
I want the request_has_connection() and get_request_connection() functions accessible from all view functions and maybe from models.py as well. Right now, I'm thinking they all belong in my blueprint init.py, which currently contains:
from flask import Blueprint
main = Blueprint('main',__name__)
from . import views
and that my request teardown function would be registered as
#main.teardown_request
def close_db_connection(ex):
<blah-blah-blah>
Is this right?

Django template loader behavior? (got Django TemplateDoesNotExist exception)

Folder Structure
I'm currently learning Django from the Django book. I have the following directory structure:
.
└── mysite
├── books
│   ├── __init__.py
│   ├── models.py
│   ├── templates
│   │   ├── search_form.html
│   │   └── search_results.html
│   ├── tests.py
│   └── views.py
├── contact
│   ├── forms.py
│   ├── __init__.py
│   ├── templates
│   │   └── contact_form.html
│   └── views.py
├── manage.py
└── mysite
├── __init__.py
├── settings.py
├── templates
│   ├── base.html
│   ├── current_datetime.html
│   └── hours_ahead.html
├── urls.py
├── views.py
└── wsgi.py
Where books, contact, and mysite are folders. I also have a separate templates subfolder for each of those folders to store templates.
Story
Now, inside /mysite/settings.py, I have the following lines:
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates').replace('\\', '/'),
)
Inside /contact/views.py, I have the following line (note that render here is from django.shortcuts):
return render(request, 'contact_form.html', {'form': form})
However, the line above gives me a TemplateDoesNotExist exception. This is because the template loader looks for the file contact_form.html under /mysite/templates/ instead of /contact/templates/.
Fair enough, even though I don't understand why that's the case. But, I have another case where it behaves differently.
Recall in the file structure above, I also have books/views.py. In it, I have the following lines (in different logical blocks):
return render(request, 'search_results.html',
{'books': books, 'query': q})
and
return render(request, 'search_form.html', {'errors': errors})
If you look back above, search_results.html and search_form.html are under the /books/templates/ folder, not /mysite/templates/ folder, and yet the template loader managed to find those files. Note that it still works even when I move search_results.html and search_form.html into /mysite/templates/.
So my question is, why is there a difference in where the loader looks for templates?
Files
Anyway, here's what my /contact/views.py looks like:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.core.mail import send_mail
from forms import ContactForm
import os
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(
cd['subject'],
cd['message'],
cd.get('email', 'noreply#example.com'),
['siteowner#example.com'],
)
return HttpResponseRedirect('/contact/thanks/')
else:
form = ContactForm()
print os.path.join(os.path.dirname(__file__), 'templates')
return render(request, 'contact_form.html', {'form': form})
Here's my /books/views.py:
from django.shortcuts import render
from django.http import HttpResponse
from books.models import Book
def search(request):
errors = []
if 'q' in request.GET:
q = request.GET['q']
if not q:
errors.append('Enter a search term.')
elif len(q) > 20:
errors.append('Please enter at most 20 characters.')
else:
books = Book.objects.filter(title__icontains=q)
return render(request, 'search_results.html',
{'books': books, 'query': q})
return render(request, 'search_form.html', {'errors': errors})
Since you apparently do have the app directories template loader installed, and since it works on your books app, I can only conclude you don't have contact in settings.INSTALLED_APPS.

Categories

Resources