Home Php C# Sql C C++ Javascript Python Java Go Android Git Linux Asp.net Django .net Node.js Ios Xcode Cocoa Iphone Mysql Tomcat Mongodb Bash Objective-c Scala Visual-studio Apache Elasticsearch Jar Eclipse Jquery Ruby-on-rails Ruby Rubygems Android-studio Spring Lua Sqlite Emacs Ubuntu Perl Docker Swift Amazon-web-services Svn Html Ajax Xml Java-ee Maven Intellij-idea Rvm Macos Unix Css Ipad Postgresql Css3 Json Windows-server Vue.js Typescript Oracle Hibernate Internet-explorer Github Tensorflow Laravel Symfony Redis Html5 Google-app-engine Nginx Firefox Sqlalchemy Lucene Erlang Flask Vim Solr Webview Facebook Zend-framework Virtualenv Nosql Ide Twitter Safari Flutter Bundle Phonegap Centos Sphinx Actionscript Tornado Register | Login | Edit Tags | New Questions | 繁体 | 简体


10 questions online user: 36

0
votes
answers
30 views
+10

插入HTML到MySQL數據庫顯示類型錯誤

-3

我正在開發一個Web應用程序使用Flask。在某些時候,我必須插入某些HTML腳本到MySQL數據庫:插入HTML到MySQL數據庫顯示類型錯誤

<h3>Welcome!</h3> 
<p>Some text</p> 

當我將其插入到數據庫中(當它被瓶中的「render_template」函數返回):



<h3>Welcome!</h3>



<p>Some text</p> 

我得到以下錯誤:

TypeError: ProgrammingError(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '\\\\n\\n<h3>Welcome!</h3>\\n\\n\\n\\n<p>Some text' at line 1") is not JSON serializable

我第一次不明白什麼JSON序列化「的意思,我想知道我做錯了。我已經嘗試脫線( ),但它仍然顯示相同的錯誤。爲什麼?我很感謝你能提供的任何答案。

+0

where is SQL query? – furas

沙发
0
0

編寫HTML時數據庫通常用於甲解決方案:

1)簡單地轉換數據庫字段類型成團塊這樣它將接受二進制數據,然後編碼HTML爲二進制(下面例子)。 2)將數據庫字段保留爲文本字段,但base64對數據進行編碼,以便數據庫不會抱怨非法字符。

# Example for case 1. 
# Note that you need to make sure the database field is a blob: 
html = '<h3>Welcome!</h3>
<p>Some text</p>' 
bin = html.encode() 
dbhandle.execute('INSERT INTO script (various fields, binhtml) VALUES (..., bin)') 
# When you read back the data, remember to decode. 
dbhandle.execute('SELECT binhtml FROM script WHERE...') 
resultset = dbhandle.fetchall() 
htmlresult = resultset.decode() 

# Example for case 2. 
# Database field can be a text/varchar type because base64 ensures it will work. 
import base64 
html = '<h3>Welcome!</h3>
<p>Some text</p>' 
# Convert HTML into base64 encoded *text* so it can be stored in text field. 
encoded = base64.b64decode(html.encode()).decode() 
# Do the database INSERT. 
... 
# Retrieve the stored text from the database and convert back to HTML 
dbhandle.execute('SELECT encodedhtml FROM script WHERE...') 
resultset = dbhandle.fetchall() 
htmlresult = base64.b64decode(resultset).decode() 
0
votes
answers
29 views
+10

Python日程安排在Flask中不起作用

1

我正在將Schedule導入Flask。我的項目包含WSGI但我對FlaskWSGI之間的關係知之甚少。現在我有三個主要文件:Python日程安排在Flask中不起作用

  • wsgi.py:自動生成其他工具。
  • app.py:我在這裏提出客戶請求。用於測試Schedule

我想在啓動服務器時啓動一項長期任務。這裏是wsgi.py部分:

# -*- coding: utf-8 -*- 
from threading import Thread 
import test 


t = Thread(target=test.job) 
t.start() 

if __name__ == '__main__': 
    ... 

正如你看到我啓動一個線程,並讓it.Here就業工作是我的test.py

import schedule 


def job(): 
    schedule.every(1).seconds.do(pr) 


def pr(): 
    print("I'm working...") 

我的問題是,job永遠不會發生。

沙发
0
0

我發現我的問題,我從來沒有讓日程表執行任務。現在wsgi.py看起來像這樣。

# -*- coding: utf-8 -*- 
from threading import Thread 
import test 

schedule.every(1).seconds.do(test.job) 
t = Thread(target=test.run_schedule) 
t.start() 

if __name__ == '__main__': 
    ... 

而且test.py

import schedule 
import time 

start_time = time.time() 


def job(): 
    print("I'm working..." + str(time.time() - start_time)) 


def run_schedule(): 
    while True: 
     schedule.run_pending() 
     time.sleep(1) 

爲了在單獨的線程工作,我創建一個線程,該線程我循環每1ms。在循環中,schedule調用run_pending如果超時(在我的情況下爲1秒)調用job

67
votes
answers
11 views
+10

Why use Tornado and Flask together?

As far as I can tell Tornado is a server and a framework in one. It seems to me that using Flask and Tornado together is like adding another abstraction layer (more overhead). Why do people use Flask and Tornado together, what are the advantages?

up vote 50 down vote accepted favorite
沙发
+500
+50

According to this question it is because Flask is blocking and Tornado is non-blocking.

If one uses Tornado as a WSGI server and Flask for url routing + templates there shouldn't be any overhead. With this approach you aren't using Flask's web server, so there isn't really an extra layer of abstraction.

However, if one is using Flask just for the templates they could use Tornado with Jinja2 which is the template engine that Flask uses.

這就是我想知道的。謝謝! - 3月11日 - 12月4日18:08

主要鏈接被打破,應該指向:flask.pocoo.org/docs/0.10/deploying/wsgi-standalone/#tornado - Jason Parham 2014年10月28日17:41

+150

I always thought using Flask & Tornado together was stupid, but it actually does make sense. It adds complexity though; my preference would be to just use Tornado, but if you're attached to Flask, then this setup works.

Flask is (reportedly) very nice to use, and simpler than Tornado. However, Flask requires a WSGI server for production (or FCGI, but that's more complicated). Tornado is pretty simple to setup as a WSGI server:

from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from yourapplication import app

http_server = HTTPServer(WSGIContainer(app))
http_server.listen(5000)
IOLoop.instance().start()

In this situation the developer just needs to worry about the Flask app. Tornado just acts as a server.

It's also possible to handle some requests (for example, websockets, which don't play nice with WSGI) using Tornado, and still do the majority of your work in Flask. In theory, you'll get the simplicity of Flask with the async performance of Tornado.

除非我弄錯了,否則在Flask應用程序中阻止活動仍會破壞並掛起Tornado反應堆,對吧? - DeaconDesperado 2013年4月9日18:44

是的,燒瓶會堵塞。但是,如果您在不同的服務器下運行它,則不會改變。 - Cole Maclean 2013年4月12日5:12

我完全放棄了Flask和UWSGI,只使用Mako模板。使用Mako需要大約30行代碼,所以現在我有路由,處理程序和模板(這幾乎就是框架)。我的應用程序由supervisord管理,它完成並運行良好,沒有Flask的空間。 - 3k- 2015年4月4日19:21

@ 3k-有任何代碼嗎?:) - Zelphir 2016年11月7日14:55

+20

instead of using Apache as your server, you'll use Tornado (of course as blocking server due to the synchronous nature of WSGI).

但如果這是真的,那麼使用Tornado而不是燒瓶網絡服務器是什麼意思呢?在這種情況下,你確定Tornado會阻塞嗎? - Zelphir 2016年11月7日14:54

0

Use each one for what is better at, but take into account that the mix don't always get the performance gains you are looking for.

This benchmark, https://gist.github.com/andreif/6088558, for example, question what combination of frameworks is faster, you must adapt the example to your main use case. On this example, flask+tornado don't deliver the expected performance gains.

0
votes
answers
30 views
+10

蟒蛇*僅在服務器列表語法錯誤,代碼本地客戶機上工作正常

1

當我執行我的外部瓶服務器上我的代碼,我得到以下服務器端錯誤:蟒蛇*僅在服務器列表語法錯誤,代碼本地客戶機上工作正常

2017-12-03 02:40:53 ", line 
2017-12-03 02:40:53 430 
2017-12-03 02:40:53 
2017-12-03 02:40:53  
2017-12-03 02:40:53 combinedheader = ["Protein", "MW", *listheadersSpC, *listheadersNSAF, *listheadersloge] 
2017-12-03 02:40:53  
2017-12-03 02:40:53 
2017-12-03 02:40:53^
2017-12-03 02:40:53 SyntaxError 
2017-12-03 02:40:53 : 
2017-12-03 02:40:53 invalid syntax 
2017-12-03 02:40:53 

這是行導致悲傷的代碼:
combinedheader = ["Protein", "MW", *listheadersSpC, *listheadersNSAF, *listheadersloge]

在本地,代碼運行得很好。還要注意的是,當在服務器上單獨執行下面的代碼返回沒有錯誤:

list1 = ['a'] 
list2 = ['d' , 'e' , 'f'] 
list3 = ["Hi", "there", *list1, *list2] 
print(list3) 

Retuns:[ '您好', '有', '一個', 'd', 'E', 'F']

編輯:代碼運行在使用Python的虛擬環境的Web應用程序上。 webapp和virtualenv python = 3.6。本地客戶端運行相同版本的Python,相同的已安裝模塊。

+0

I認爲你在服務器上使用了錯誤版本的python(可能是2.x),你最好確認服務器python的版本號 – hsfzxjy

+0

謝謝,我在發佈這個問題之前檢查了它服務器:版本3.6。本地版本:版本3.6 – PeptideWitch

+0

但是你可能會想到某些東西,也許我在服務器上設置的虛擬環境沒有正確傳遞我的代碼,只需再次檢查,主服務器使用2.7.6,而我的虛擬環境使用3.6。是吧;會報告回 – PeptideWitch

沙发
0
1

代碼os.system("python myscript.py")不會總是使用您當前的解釋器。相反,它取決於環境變量。所以你必須明確指定解釋器的絕對路徑。

對於大多數情況,您可以使用sys.executable獲取當前的翻譯。然而,它不適用於uwsgi :-(其中sys.executable將返回uwsgi二進制文件的路徑。因此,在這種情況下,您必須將可執行路徑硬編碼到virtualenv解釋器,如下所示:os.system("path/to/venv/python myscript.py")

+0

工作就像一個魅力,感謝指導我通過這個過程 – PeptideWitch

0
votes
answers
26 views
+10

後臺線程用Flask-Socketio啓動兩次

0

我已經使用socketio創建了一個小的Flask webapp,它應該可視化一個brew控制器。硬件是Raspberry Pi,控制器部分(硬件綁定和數據收集)是在獨立的後臺線程中完成的,該線程在create_app開始。我需要確保後臺線程只開始一次(即使我創建了多個應用程序對象)。所以我使用BrewController.get_instance()函數來實現某種單例模式。後臺線程用Flask-Socketio啓動兩次

import os 
import time 
import threading 
import arrow 
from sqlitedict import SqliteDict 
from flask import Flask 
from flask_bootstrap import Bootstrap 
from flask_socketio import SocketIO 
from flaskext.lesscss import lesscss 

from config import config 
from .brewcontroller import BrewController 

background_thread = threading.Thread() 

# Flask Plugins 
bootstrap = Bootstrap() 
socketio = SocketIO() 
brew_controller = BrewController.get_instance() 


db = SqliteDict('process_data.sqlite', tablename='pd', autocommit=False) 
db.setdefault('t', []) 
db.setdefault('temp_sp', []) 
db.setdefault('temp_ct', []) 
db.setdefault('ht_pwr', []) 
db.commit() 

from . import events # noqa 


def create_app(config_name=None): 
    app = Flask(__name__) 

    if config_name is None: 
     config_name = os.environ.get('PIBREW_CONFIG', 'development') 
    app.config.from_object(config[config_name]) 

    # init flask plugins 
    lesscss(app) 
    bootstrap.init_app(app) 
    socketio.init_app(app) 

    # create blueprints 
    from .main import main as main_blueprint 
    app.register_blueprint(main_blueprint, url_prefix='/') 

    # init the brew controller and start the background task if none 
    # exists yet 
    print(brew_controller) 
    if not brew_controller.initialized: 
     brew_controller.init_app(app) 

     background_thread = threading.Thread(
      target=process_controller, 
      args=[app.config['PROCESS_INTERVAL']], 
      daemon=True 
     ) 
     print('controller started') 
     background_thread.start() 

    return app 


def process_controller(interval): 

    while(1): 

     current_time = arrow.now() 
     brew_controller.process() 

     data = { 
      't': current_time.format('HH:mm:ss'), 
      'temp_sp': '{:.1f}'.format(brew_controller.temp_setpoint), 
      'temp_ct': '{:.1f}'.format(brew_controller.temp_current), 
      'ht_en': brew_controller.heater_enabled, 
      'mx_en': brew_controller.mixer_enabled, 
      'ht_pwr': '{:.1f}'.format(brew_controller.heater_power_pct), 
      'ht_on': brew_controller.heater_on, 
     } 

     x = db['t'] 
     x.append(data['t']) 
     db['t'] = x 

     db['temp_sp'].append(data['temp_sp']) 
     db['temp_sp'] = db['temp_sp'] 

     db['temp_ct'].append(data['temp_ct']) 
     db['temp_ct'] = db['temp_ct'] 

     db['ht_pwr'].append(data['ht_pwr']) 
     db['ht_pwr'] = db['ht_pwr'] 

     db.commit() 

     socketio.emit('update', data) 
     time.sleep(interval) 

但是線程仍然開始兩次,我甚至得到兩個不同的BrewController實例。所以我最終得到了兩倍於我的數據庫和重複值的數據。

後,我打電話manage.py運行看起來像這樣(我打印的brewcontroller實例,看看它們是不同的)輸出:

<pibrew.brewcontroller.BrewController object at 0x105777208> 
<pibrew.brewcontroller.BrewController object at 0x105777208> 
controller started 
* Restarting with stat 
<pibrew.brewcontroller.BrewController object at 0x10ca04240> 
<pibrew.brewcontroller.BrewController object at 0x10ca04240> 
controller started 
* Debugger is active! 
* Debugger pin code: 121-481-821 
(31213) wsgi starting up on http://0.0.0.0:5000 

我發現通過設置use_reloader說法,我可以抑制這個我manage.py爲False。

@manager.command 
def run(): 
    app = create_app() 
    socketio.run(app, host='0.0.0.0', port=5000, use_reloader=False) 

但是,首先這種雙重啓動的原因是什麼。對我來說,似乎有兩個創建的進程。有人可以解釋發生了什麼,以及防止這種情況的最佳方法是什麼。

沙发
0
1

當你使用重載器時,實際上有兩個創建的進程。重新加載器啓動一個主進程,唯一的目的是觀察所有源文件的變化。重新加載進程將實際的服務器作爲子進程運行,當它發現其中一個源文件被修改時,它會殺死服務器並啓動另一個源文件。

一個稍微好一點的開始你的線程可能是做一個before_first_request處理方法。這樣,只有子進程中的實際服務器在獲得第一個請求時纔會啓動線程。重新加載進程永遠不會收到請求,所以它永遠不會嘗試啓動一個線程。

+0

我喜歡使用'before_first_request'處理程序的想法。但是我仍然有點麻煩,因爲我不知道該把它放在哪裏。當我使用工廠函數'create_app'時,模塊中沒有可用的應用程序對象。我也無法註冊藍圖。 – MrLeeh

+0

您可以在藍圖上使用[before_app_first_request](http://flask.pocoo.org/docs/0.11/api/#flask.Blueprint.before_app_first_request)。 – Miguel

板凳
0
0

基於Miguels Answer我放在before_first_request處理我create_app函數處理brew_controller創建並啓動後臺線程裏面。

def create_app(config_name=None): 
    app = Flask(__name__) 

    # ... 

    @app.before_first_request 
    def init_brew_controller(): 
     # init the brew controller and start the background task if none 
     # exists yet 
     if not brew_controller.initialized: 
      brew_controller.init_app(app) 

      background_thread = threading.Thread(
       target=process_controller, 
       args=[app.config['PROCESS_INTERVAL']], 
       daemon=True 
      ) 
      background_thread.start() 
      app.logger.info('started background thread') 

    return app 

現在我可以使用reloader,而後臺線程只能啓動一次。

37
votes
answers
29 views
+10

How to set React to production mode when using Gulp

I need to run React in production mode, which presumably entails defining the following somewhere in the enviornment:

process.env.NODE_ENV = 'production';

The issue is that I'm running this behind Tornado (a python web-server), not Node.js. I also use Supervisord to manage the tornado instances, so it's not abundantly clear how to set this in the running environment.

I do however use Gulp to build my jsx files to javascript.

Is it possible to somehow set this inside Gulp? And if so, how do I check that React is running in production mode?

Here is my Gulpfile.js:

'use strict';

var gulp = require('gulp'),
        babelify = require('babelify'),
        browserify = require('browserify'),
        browserSync = require('browser-sync'),
        source = require('vinyl-source-stream'),
        uglify = require('gulp-uglify'),
        buffer = require('vinyl-buffer');

var vendors = [
    'react',
    'react-bootstrap',
    'jquery',
];

gulp.task('vendors', function () {
        var stream = browserify({
                        debug: false,
                        require: vendors
                });

        stream.bundle()
                    .pipe(source('vendors.min.js'))
                    .pipe(buffer())
                    .pipe(uglify())
                    .pipe(gulp.dest('build/js'));

        return stream;
});

gulp.task('app', function () {
        var stream = browserify({
                        entries: ['./app/app.jsx'],
                        transform: [babelify],
                        debug: false,
                        extensions: ['.jsx'],
                        fullPaths: false
                });

        vendors.forEach(function(vendor) {
                stream.external(vendor);
        });

        return stream.bundle()
                                 .pipe(source('build.min.js'))
                                 .pipe(buffer())
                                 .pipe(uglify())
                                 .pipe(gulp.dest('build/js'));

});

gulp.task('watch', [], function () {
    // gulp.watch(['./app/**/*.jsx'], ['app', browserSync.reload]);
    gulp.watch(['./app/**/*.jsx'], ['app']);
});

gulp.task('browsersync',['vendors','app'], function () {
        browserSync({
            server: {
                baseDir: './',
            },
            notify: false,
            browser: ["google chrome"]
    });
});

gulp.task('default',['browsersync','watch'], function() {});
up vote 29 down vote accepted favorite
沙发
+290
+50

2017 - Edit: anyone trying to set up React in Gulp for a new project: Just use create-react-app


Step I: Add the following to your gulpfile.js somewhere

gulp.task('apply-prod-environment', function() {
    process.env.NODE_ENV = 'production';
});

Step II: Add it to your default task (or whichever task you use to serve/build your app)

// before: 
// gulp.task('default',['browsersync','watch'], function() {});
// after:
   gulp.task('default',['apply-prod-environment', 'browsersync','watch'], function() {});

OPTIONAL: If you want to be ABSOLUTELY CERTAIN that you are in prod mode, you can create the following slightly enhanced task instead of the one in Step I:

gulp.task('apply-prod-environment', function() {
    process.stdout.write("Setting NODE_ENV to 'production'" + "
");
    process.env.NODE_ENV = 'production';
    if (process.env.NODE_ENV != 'production') {
        throw new Error("Failed to set NODE_ENV to production!!!!");
    } else {
        process.stdout.write("Successfully set NODE_ENV to production" + "
");
    }
});

Which will throw the following error if NODE_ENV is ever not set to 'production'

[13:55:24] Starting 'apply-prod-environment'...
[13:55:24] 'apply-prod-environment' errored after 77 μs
[13:55:24] Error: Failed to set NODE_ENV to production!!!!

據我所知,沒有這種情況。可選步驟實際上是不必要的。 - 君主瓦迪亞2016年2月24日22:20

如果我錯了,請糾正我,但是gulp中的任務順序在技術上是不保證的。那麼在應用prod環境之前,觀察和瀏覽器同步不會發生嗎? - 克里斯2016年3月22日9:18

我期待一個明顯的大小變化,但似乎差異是2ko差異(未壓縮),有人可以證實嗎? - Vadorequest 2016年3月29日10:15

對我不起作用 - GN。2016年11月30日6:06

+70

Similar to the other answers, but hopefully gives someone a starting point:

var vendorList = ['react', 'react-dom'];

gulp.task('vendor-dev', function() {
    browserify()
        .require(vendorList)
        .bundle()
        .on('error', handleErrors)
        .pipe(source('vendor.js'))
        .pipe(gulp.dest('./build/dev/js'));
});

gulp.task('vendor-production', function() {
    process.env.NODE_ENV = 'production';
    browserify()
        .require(vendorList)
        .bundle()
        .on('error', handleErrors)
        .pipe(source('vendor.js'))
        .pipe(buffer())
        .pipe(uglify({ mangle: false }))
        .pipe(gulp.dest('./build/production/js'));
});

The main difference is I am explicitly setting the NODE_ENV prior to bundling the vendor libraries. Gulp tasks aren't guaranteed to run in order.

Am I running in production mode?

If you remove the uglify line (and prior buffer) you will notice that both the dev and production builds are near identical in size - and match in line count.

The difference is the production version will be littered with:

"production" !== "production" ? [show dev error] : [no nothing]

Most reputable minify'ers (I believe) will strip out deadend code, such as the above, which will always result in false.

But really how do I tell?

Easiest method to be sure, would be goto the console of your running application and type:

React.createClass.toString();

The output should be:

"function (e){var t=function(e,t,n){this.__reactAutoBindMap&&c(this),"[....and more and more]

If you find the createClass in the react source, you will see:

createClass: function (spec) {
    var Constructor = function (props, context, updater) {
      // This constructor is overridden by mocks. The argument is used
      // by mocks to assert on what gets mounted.

      if ("production" !== 'production') {
        "production" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: react-legacyfactory') : undefined;
      }

      // Wire up auto-binding
      if (this.__reactAutoBindMap) {
        bindAutoBindMethods(this);
      }

Notice how the console output skips straight through to this.__reactAutobind, because you are running in production mode, and using an minify'er, all the !== 'production' warngins and checks have been skipped over.

大。在任務本身中明確設置NODE_ENV是它對我有用的唯一方式。 - 費爾南多2016年8月4日6:57

別擔心。是的,這對我來說是一樣的 - 克里斯8月4日在9:32

+10

To set React in production mode you need to set your NODE_ENV variable to production and uglify your JS as an extra step.

You're already taking care of the uglification, for setting your NODE_ENV variable :

  • Set the variable while running the gulp task :

NODE_ENV='production' gulp

  • OR set it from inside your gulpfile by doing something like this :

gulp.task('set-production-env', function() { return process.env.NODE_ENV = 'production'; });

如何檢查React是否在生產模式下工作?有沒有辦法檢查開發控制台中的模式? - vgoklani 2015年9月14日12:41

一種方法是觸發會引起警告的內容並檢查控制台中是否存在警告日誌。例如,將數組映射到一堆組件,並且不給它們一個鍵。如果沒有任何內容寫入控制台,那麼您處於生產模式。此外,請確保反應庫已正確縮小,uglified和gzip文件大小。 - Rakan Nimer 2015年9月15日7:34

謝謝你的幫助:) - vgoklani 2015年9月29日19:29

另一種方法是檢查最終縮小的app / browserify捆綁包的大小。我剛看到我的捆綁尺寸下降了大約100kB的生產設置。 - akarve 2016年3月18日3:11

0

Also you may use handy way with gulp-environments:

var environments = require('gulp-environments');

var production = environments.production;

gulp.src(paths.js)
    .pipe(concat("app.js"))
    // only minify the compiled JS in production mode
    .pipe(production(uglify()))
    .pipe(gulp.dest("./public/app/js/"));

To run gulp in production mode:

gulp build --env=production
0

Unfortunately none of the above answers work, because setting process.env.NODE_ENV has no effect in Browserify. The resulting bundle still has process.env.NODE_ENV references in it and hence

  • Browserify will not require() the React production version modules,
  • the minifier will not be able to remove dead code, and
  • the application will still be running in debug mode.

This is unfortunately not the only place where this approach is offered as the correct answer :-(


The correct approach can be found in e.g.

You need to switch the envify transform to be a global one, e.g.

# note the "-g" instead of the usual "-t"
$ browserify ... -g [ envify --NODE_ENV production ] ....

or in gulpfile.js

browserify(...)
    ...
    .transform('envify', {
        global:   true, // also apply to node_modules
        NODE_ENV: debug ? 'development' : 'production',
    })
    ...
    .bundle()
    ...
    .pipe(gulpif(!debug, babelMinify())) // my example uses gulp-babel-minify
    ...
76
votes
answers
15 views
+10

Flask user authentication

I have an application that will use flask and mongodb; I will probably host it on rackspace.

I need to understand how flask authenticating works. I have not found much information on the subject. Is there a complete tutorial on how to roll your own solution? If not, I certainly would like to hear some thoughts on how you would approach it for a a flask app.

Big PS:

I just thought about it. I also need to open a real API. A part of that API will be used for AJAX on the front end. How do i secure that part of the app?

Can anyone explain API auth requests?

up vote 60 down vote accepted favorite
沙发
+600
+50

I would suggest using the flask-login extension, it makes session management really easy to add to your flask application, and provides a nice documentation which covers in details every aspect of the extension.

這是一個經證實的擴展嗎?你有沒有在生產中使用它?它有多安全? - pocorschi 2011年8月7日19:25

我只在一個應用程序中使用它,它看起來做得很好。但是,如果您真的擔心安全問題,那麼您可能想要自己查看其代碼(或者您使用的任何庫的代碼)。 - mdeous 2011年8月7日20:46

它相當安全,恕我直言。使用MD5,如果您擔心碰撞,可以將其更改為SHA2。 - Dhaivat Pandya 2011年8月10日9:31

雖然我沒有理由相信燒瓶登錄是不安全的,但我想在這裡提一下並提及炫耀這個或那個散列算法作為安全條是非常誤導的。安全!=算法和安全!=比特長! - Yaniv Aknin 12年12月24日中午12點

@DhaivatPandya flask-login根本不使用任何算法,因為由程序員來驗證 - 並存儲 - 憑證。 - dom013年9月2日10:59

+120

I don't think that flask has any authentication built-in, only support for tracking sessions.

Here are some snippets for basic HTTP authentication and authentication with some third-party providers. Otherwise you will need to roll your own or use a framework that has this baked in (like Django)

Here is a discussion thread on this topic with a useful link

謝謝rupello。這確實是我正在尋找的。如何滾動的一步一步。我自己的 。據我所知,燒瓶可以跟踪會話,所以我需要在某種檢查器中裝飾受限制的功能。但是ajax部分怎麼樣?還有..一篇論文將幫助我做出錯誤的選擇 - pocorschi 2011年8月7日13:57

+40

Flask-Login doesn't, technically, do authentication - it does session management, leaving the (tricky to securely implement) authentication details to you. Something like Flask-Security actually implements both session management and authentication (also nice-to-haves like password recovery/reset and the like), at the cost of having to have explicit support for your database.

0
votes
answers
16 views
+10

燒瓶:如何在一定的時間內保留一個變量的值?

0

我在Messenger平臺上製作了一個聊天機器人,並詢問用戶一系列的問題。但是,當用戶回答第一個問題時,它直接回到Api.AI中的回退意圖,我必須保持回答同樣的問題直到下一個問題。 我認爲設置一個sessionID將解決這個問題,但它沒有。燒瓶:如何在一定的時間內保留一個變量的值?

ai = ApiAI(os.environ["APIAI_TOKEN"]) 
req = ai.text_request() 
    req.session_id = str(uuid.uuid1(int(str(senderID)[0:15]))) 

事實證明的UUID1的輸出變化時,有時當一個新的請求(當用戶回答了這個問題),即使senderID是相同的(senderID是通過Facebook的發送的用戶ID)。所以,我試圖將uuid1的值保存到字典中,如果用戶回答第一個問題,新請求將首先檢查字典中的senderID,如果它已存在,則不會爲同一個senderID生成新的uuid。 但問題是有時當一個新的請求(來自同一用戶)遇到heroku時,字典中的值消失了。這不會每次都發生,但約90%的時間。 以下是新請求的日誌。

2017-11-18T09:43:03.784670+00:00 heroku[router]: at=info method=POST path="/" host=website.com request_id=ab6d6488-0343-4c68-9b2a-d6faf2ee2302 fwd="173.252.123.140" dyno=web.1 connect=0ms service=633ms status=200 bytes=161 protocol=https 

我該如何保留價值。還有其他方法嗎? 我是一個新手,我一直陷在這個問題一個星期。

沙发
0
0

字典可能沒有綁定到會話,可能會超出範圍並從內存中清除。所以你存儲的任何東西都不會被可靠地持久化。有兩種方法可以解決這個問題。首先是使用像Redis這樣的獨立緩存服務器來存儲你的值,其次是在Flask本身中使用緩存工具。

如果你打算使用外部Redis的服務器,你可以不喜歡下面

import redis 

# instantiate the redis db 
REDIS_HOST = <REDIS_HOST> 
REDIS_PORT = <REDIS_PORT> 
redis_db = redis.StrictRedis(host=REDIS_HOST,port=REDIS_PORT) 

key = sender_id 
event = {} 
event["uuid"] = uuid1 
event["sender_id"] = sender_id 
redis_db.delete(key) #remove old keys 
redis_db.hmset(key, event) 
redis_db.expire(key, 259200) #3 days (you can set your own expire time in seconds 

代碼可以檢查高速緩存,看看是否存在某個值使用

key = sender_id 
if redis_db.exists(key): 
    event = redis_db.hgetall(key) 

第二方式是使用燒瓶的緩存工具與SimpleCache或LRUCache。下面是緩存值,以後可以用

key = sender_id 
event = cache.get(key) 

但是你需要記住retrived使用SimpleCache

from werkzeug.contrib.cache import SimpleCache 
cache = SimpleCache() 

key = sender_id 
event = {} 
event["uuid"] = uuid1 
event["sender_id"] = sender_id 

cache.set(key,event,timeout=259200) # 3 days 

的例子,如果你用使用的高速緩存工具的第二選擇相同的服務器,然後每次您的服務器重新啓動時,您將丟失值,但它們應該在整個會話期間都可用。

+0

當服務器重新啓動時我不會失去redis的值嗎? –

+0

如果你把它安裝在同一臺機器上,是的。但是大多數我認識的人,至少有一些新開發人員使用某種雲服務來進行redis(azure,aws等),因爲它運行在不同的服務器上,所以他們不會重置。 此外,如果答案幫助你,請接受它 – Akshay

0
votes
answers
30 views
+10

如何將模板Flask中的對象顯示爲json?

-4

我有一個路由方法:如何將模板Flask中的對象顯示爲json?

@app.route('/add', methods=['GET']) 
def add_view(): 
    return render_template('add.html', categories=api.categories()) 

然後我試圖顯示categories爲JSON內模板add.html

{{ categories | json }} 

它不工作

+0

請提供什麼行不通的詳細信息,準確。錯誤消息,錯誤的行爲描述,一切 –

沙发
0
0

我覺得很難理解到底是什麼你正在尋找在這裏,所以我想看到更多的細節,但這裏是基於我認爲你問一個答案(我將修改這SUI你的需求/如果事情改變,完全刪除這個評論)。

你調用api.categories()並打算使這是JSON你的HTML模板,是嗎?

確定什麼,我建議你在這裏是爲了確保api.categories()正在返回的dict一個實例。例如,您的通話api.categories()返回應該是這樣的:

{ 
    "testKey1": "testValue1", 
    "testKey2": "testValue2" 
} 

現在在你的HTML模板來渲染這是JSON。您可以使用以下進口導入瓶模塊中的json模塊:

import json 

現在,在您add_view方法的return語句將如下:

return render_template('add.html', categories=json.dumps(api.categories())) 

你現在可以做類似如下在你的HTML模板中:

<script> 
    document.write("{{categories}}"); 
<script> 

這應該爲你呈現你的JSON就好了。

91
votes
answers
20 views
+10

using Flask and Tornado together?

I am a big fan of Flask - in part because it is simple and in part because has a lot of extensions. However, Flask is meant to be used in a WSGI environment, and WSGI is not a non-blocking, so (I believe) it doesn't scale as well as Tornado for certain kinds of applications.

Since each one has an URL dispatcher which will call a function, and both will use Python files (in Django you dont launch the python file but in flask or tornado you do) do does it make sense to have two seperate parts to your website - one part running the non-blocking jobs with Tornado, and the other part written with Flask?

If this is a good idea, how would you go about sharing cookies / sessions between Flask and Tornado? Will I run into issues, since Flask will use it own system and Tornado will use its own system?

up vote 87 down vote accepted favorite
沙发
+870
+50

i think i got 50% of the solution, the cookies are not tested yet, but now i can load Flask application using Tornado, and mixing Tornado + Flask together :)

first here is flasky.py the file where the flask application is:

from flask import Flask
app = Flask(__name__)

@app.route('/flask')
def hello_world():
  return 'This comes from Flask ^_^'

and then the cyclone.py the file which will load the flask application and the tornado server + a simple tornado application, hope there is no module called "cyclone" ^_^

from tornado.wsgi import WSGIContainer
from tornado.ioloop import IOLoop
from tornado.web import FallbackHandler, RequestHandler, Application
from flasky import app

class MainHandler(RequestHandler):
  def get(self):
    self.write("This message comes from Tornado ^_^")

tr = WSGIContainer(app)

application = Application([
(r"/tornado", MainHandler),
(r".*", FallbackHandler, dict(fallback=tr)),
])

if __name__ == "__main__":
  application.listen(8000)
  IOLoop.instance().start()

hope this will help someone that wants to mix them :)

如何在Tornado中添加異步方法?你能在燒瓶路線上使用async嗎? - Merlin 12年4月4日19:01

我知道Flask是一個微框架。但是Tornado並不是一個微框架,但它有一個強大的http服務器。假設您不需要關注WSGI“容器”的潛在交換,為什麼不開發Tornado提供的產品呢? - 傑森10月27日在18:40

Flask很好,因為它的擴展,所有東西都有Flask的擴展,所以不需要重新發明輪子。@Merlin我認為這不是一個簡單的方法,Flask使用WSGI並且WSGI不是異步的。 - Abdelouahab Pp 12年4月4日14:02

這真的可行嗎?你最終使用這個,還是只使用龍捲風? - Mittenchops 2014年4月7日20:08

@AbdelouahabPp,雖然Flask使用WSGI並且WSGI不是異步的,但是龍捲風可以接受異步連接然後我們每個請求都可以在不同的線程中運行(我不確定),然後我們可以讓異步龍捲風改為使用Gunicorn同步worker類就像Apache pre-fork模塊一樣。 - 安迪2015年10月15日3:48

+40

Based on 1 and 2, the combined and shorter answer is

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":

    from tornado.wsgi import WSGIContainer
    from tornado.httpserver import HTTPServer
    from tornado.ioloop import IOLoop

    http_server = HTTPServer(WSGIContainer(app))
    http_server.listen(8000)
    IOLoop.instance().start()

Please consider the warning about performance that has been mentioned on 2 , 3

最好單獨使用龍捲風而不是結合燒瓶和龍捲風。 - Ahmad Yoosofan 2017年3月25日15:25