简体   繁体   English

Python Flask:在投入生产时获取 URL

[英]Python Flask: getting URL when moving to production

I'm using Python from quite some time but I am totally newbie in Flask.我使用 Python 已经有一段时间了,但我是 Flask 的新手。 Can you help me with two simple questions I have been strugling two days?你能帮我解决我这两天纠结的两个简单问题吗?

I have a simple Flask app that supposed to import a XLSX or CSV, parse it and create a zip file to download.我有一个简单的 Flask 应用程序,它应该导入 XLSX 或 CSV,解析它并创建一个 zip 文件以供下载。 While I am begginig work on the parse part, I got an error when uploading the file, and I found out that the app is not saving the file altough it works when running flask locally .当我开始解析部分的工作时,上传文件时出现错误,我发现应用程序没有保存文件,尽管它在本地运行 flask 时工作 This is the code:这是代码:

test2.py测试2.py

``` from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
import pandas as pd

app = Flask(__name__)

def work(arquivo):
    df = pd.read_excel(arquivo)
    return(str(df.shape))

@app.route('/')
def start():
   return "acesse /upload"


@app.route('/upload')
def upload_file():
   return render_template('upload.html')

@app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
   if request.method == 'POST':
       f = request.files['file']
       f.save('./inbox/'+secure_filename(f.filename))
       a = work('./inbox/'+secure_filename(f.filename))
       return 'file uploaded successfully '+a

if __name__ == '__main__':
   app.run(debug = True)
```

And this is the upload.html file that I put on templates folder in production (the app runs on http://www.fabianocastello.com.br/test2/upload ):这是我在生产中放在模板文件夹中的upload.html文件(应用程序在http上运行://www.fabianocastello.com.br/test2/

    <html>
       <body>
          <form action = "http://www.fabianocastello.com.br/test2/uploaded" method = "POST" 
             enctype = "multipart/form-data">
             <p>Arquivo</p>
             <input type = "file" name = "file" accept=".csv, .xlsx" </input>
             <input type = "submit" value="Enviar arquivo"/>
          </form>   
       </body>
    </html>

when locally, the upload.html file that works is this:在本地时,有效的 upload.html 文件是这样的:

    <html>
       <body>
          <form action = "http://localhost:5000/uploader" method = "POST" 
             enctype = "multipart/form-data">
             <p>Arquivo</p>
             <input type = "file" name = "file" accept=".csv, .xlsx" </input>
             <input type = "submit" value="Enviar arquivo"/>
          </form>   
       </body>
    </html>

The error I got after uploading the file is this: Not Found The requested URL was not found on the server.上传文件后我得到的错误是: Not Found The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.如果您手动输入了 URL,请检查您的拼写并重试。

My questions are these: 1. Why the production app is not saving the uploaded file in "inbox" folder?我的问题是: 1. 为什么生产应用程序没有将上传的文件保存在“收件箱”文件夹中? 2. Is there a way that I substitute the URL in upload.html file from a variable so to I do not have to manually change the file before upload? 2. 有没有一种方法可以将upload.html 文件中的URL 替换为变量,这样我就不必在上传前手动更改文件?

Thank you all in advance.谢谢大家。

This is what the url_for method is for.这就是url_for方法的用途。 That will automatically fix "http://localhost:5000/uploader" for you.这将自动为您修复"http://localhost:5000/uploader"

However, <form action = "http://www.fabianocastello.com.br/test2/uploaded"...> points at a bigger misunderstanding.但是, <form action = "http://www.fabianocastello.com.br/test2/uploaded"...>指出了更大的误解。 It would be horrendous if you had to alter every route in your templates moving from development to production.如果您必须更改模板中从开发到生产的每条路线,那将是可怕的。 Your Flask routes needn't point to the specific domain that you're running your app on;您的 Flask 路由不必指向您正在运行应用程序的特定域; they need only point to the endpoint of the server running your app (which might be gunicorn , for example).它们只需要指向运行您的应用程序的服务器的端点(例如可能是gunicorn )。 The Mega Tuorial might be helpful here for deployment. Mega Tuorial在这里可能有助于部署。 There's also more info in the deployment docs .部署文档中还有更多信息。

With that out of the way, there's other issues that need to be dealt with:有了这些,还有其他问题需要处理:

  1. You have two route functions with the same name - upload_file .您有两个同名的路由函数 - upload_file Why?为什么? It doesn't matter that you decorated them with different URLs, you can't have two functions with the same name in the same namespace.用不同的 URL 修饰它们并不重要,在同一个命名空间中不能有两个同名的函数。
  2. The second upload_file is set to accept both GET and POST requests, but you only handle the POST case.第二个upload_file设置为接受GETPOST请求,但您只处理POST情况。 Sending a GET request to this route will error.向该路由发送GET请求会出错。

This fixes the form:这修复了表单:

<html>
   <body>
      <form action = "{{ url_for('upload_file') }}" method = "POST" 
         enctype = "multipart/form-data">
         <p>Arquivo</p>
         <input type = "file" name = "file" accept=".csv, .xlsx" </input>
         <input type = "submit" value="Enviar arquivo"/>
      </form>
   </body>
</html>

This consolidates the two route functions into one:这将两个路由功能合并为一个:

@app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
   if request.method == 'POST':
       f = request.files['file']
       f.save('./inbox/'+secure_filename(f.filename))
       a = work('./inbox/'+secure_filename(f.filename))
       return 'file uploaded successfully '+a
   else:
       return render_template('upload.html')

return 'file uploaded successfully '+a is going to give a garbage result, if any, though. return 'file uploaded successfully '+a会给出一个垃圾结果,如果有的话。 It's not going to render a template with the message, it's just going to be unstyled text.它不会用消息呈现模板,它只是无样式的文本。 It looks like you want AJAX, which would look something like this:看起来你想要 AJAX,它看起来像这样:

<html>
   <body>
      <form action = "{{ url_for('upload_file') }}" method = "POST" 
         enctype = "multipart/form-data" id="upload_file_form">
         <p>Arquivo</p>
         <input type = "file" name = "file" accept=".csv, .xlsx" </input>
         <input type = "submit" value="Enviar arquivo"/>
      </form>
      <div id="response_div"></div>
   </body>
   <script>
   $("#upload_file_form").submit(function(e) {
       e.preventDefault();
       var form = $(this);
       var url = form.attr('action');

       $.ajax({
           type: "POST",
           url: url,
           data: form.serialize(),
           context: form,
           success: function(resp) {
               $("#response_div").html(resp);   
           }
       });
   });
</script>
</html>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM