ไฟล์คงที่ใน Flask - robot.txt, sitemap.xml (mod_wsgi)


94

มีวิธีแก้ปัญหาที่ชาญฉลาดในการจัดเก็บไฟล์แบบคงที่ในไดเรกทอรีรากของแอปพลิเคชันของ Flask คาดว่าจะพบ robots.txt และ sitemap.xml ใน / ดังนั้นความคิดของฉันคือการสร้างเส้นทางสำหรับพวกเขา:

@app.route('/sitemap.xml', methods=['GET'])
def sitemap():
  response = make_response(open('sitemap.xml').read())
  response.headers["Content-type"] = "text/plain"
  return response

ต้องมีอะไรที่สะดวกกว่านี้ :)

คำตอบ:


78

วิธีที่ดีที่สุดคือตั้งค่าstatic_url_pathเป็น root url

from flask import Flask

app = Flask(__name__, static_folder='static', static_url_path='')

ควรค่าแก่การกล่าวถึงว่า static_folder ไม่จำเป็นต้องอยู่ในโฟลเดอร์โครงการ เช่น static_folder = '/ app / ui' ใช้ได้
ashic

66

@vonPetrushev ถูกต้องในการผลิตคุณจะต้องให้บริการไฟล์คงที่ผ่าน nginx หรือ apache แต่สำหรับการพัฒนาเป็นเรื่องดีที่จะมีสภาพแวดล้อมการพัฒนาของคุณที่เรียบง่ายโดยมีแอป python ของคุณให้บริการเนื้อหาแบบคงที่ดังนั้นคุณจึงไม่ต้องกังวล เกี่ยวกับการเปลี่ยนการกำหนดค่าและโครงการต่างๆ ต้องการทำเช่นนั้นคุณจะต้องการใช้SharedDataMiddleware

from flask import Flask
app = Flask(__name__)
'''
Your app setup and code
'''
if app.config['DEBUG']:
    from werkzeug import SharedDataMiddleware
    import os
    app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
      '/': os.path.join(os.path.dirname(__file__), 'static')
    })

ตัวอย่างนี้ถือว่าไฟล์คงที่ของคุณอยู่ในโฟลเดอร์ "คงที่" ปรับเปลี่ยนให้เหมาะกับสภาพแวดล้อมของคุณ


1
ขอบคุณ! นี่คือสิ่งที่ฉันต้องการ! ฉันต้องการทำสิ่งนี้เพื่อการผลิตฮีโร่ของฉัน ดูคำตอบได้ที่หัวข้อต่อไปนี้flask.pocoo.org/mailinglist/archive/2012/2/22/…
David

2
โปรดทราบ - ตอนนี้มีวิธีที่ง่ายกว่าในการจัดการ ตรวจสอบการตอบกลับของฉัน
Sean McSomething

1
มีวิธีให้ SharedDataMiddleware แก้ไขเพียงแค่ '/' เป็น index.html หรือคล้ายกันหรือไม่?
gromgull

64

คำตอบที่สะอาดสำหรับคำถามนี้คือคำตอบนี้ (เหมือนกัน) คำถาม :

from flask import Flask, request, send_from_directory
app = Flask(__name__, static_folder='static')    

@app.route('/robots.txt')
@app.route('/sitemap.xml')
def static_from_root():
    return send_from_directory(app.static_folder, request.path[1:])

สรุป:

  • ดังที่ David ชี้ให้เห็นด้วยการกำหนดค่าที่ถูกต้องคุณสามารถให้บริการไฟล์คงที่ผ่าน prod ได้
  • การค้นหา /robots.txt ไม่ควรส่งผลให้เกิดการเปลี่ยนเส้นทางไปที่ /static/robots.txt (ใน Seans ตอบยังไม่ชัดเจนในทันทีว่าทำได้อย่างไร)
  • การเพิ่มไฟล์คงที่ลงในโฟลเดอร์รูทของแอปนั้นไม่สะอาด
  • ในที่สุดโซลูชันที่นำเสนอดูสะอาดกว่าวิธีการเพิ่มมิดเดิลแวร์:

หรือถ้าคุณกำลังใช้พิมพ์เขียวคุณสามารถใช้แล้ว@bp.route(...) current_app.static_folder(นำเข้าcurrent_appจากขวดเช่นเดียวกับrequestและsend_from_directory
Sean McCarthy

23

แม้ว่านี่จะเป็นคำถามที่ตอบแล้ว แต่ฉันก็ตอบคำถามนี้ได้เพราะโพสต์นี้มีผลการค้นหาของ Google ค่อนข้างสูง แม้ว่าจะไม่ครอบคลุมในเอกสาร แต่หากคุณอ่านเอกสาร APIสำหรับตัวสร้างอ็อบเจ็กต์ Flask Application จะครอบคลุม โดยการส่งผ่านพารามิเตอร์ที่มีชื่อstatic_folderดังนี้:

from flask import Flask
app = Flask(__name__,
            static_folder="/path/to/static",
            template_folder="/path/to/templates")

... คุณสามารถกำหนดตำแหน่งที่จะให้บริการไฟล์แบบคงที่ได้ ในทำนองเดียวกันคุณสามารถกำหนด a template_folderชื่อของคุณstatic_url_pathได้


@chmike ใช่ค่าเริ่มต้นของมันแต่คุณสามารถเปลี่ยนที่โดยเอาชนะ/static static_url_path
Sean McSomething

คำตอบนี้ถูกต้อง แต่คำตอบอื่นมีความยืดหยุ่นมากกว่า อันนี้ถูก จำกัด ด้วยข้อเท็จจริงที่สามารถให้บริการเส้นทางไดเร็กทอรีเดียว
Thomas Dignan

นี่ไม่ใช่คำตอบสำหรับคำถามเดิม
Paolo Casciello

2
หากคุณตั้งค่า static_url_path เป็น "" คุณสามารถให้บริการไฟล์จาก /
Beau

สิ่งนี้บังคับให้ Flask ให้บริการไฟล์คงที่ จะเป็นอย่างไรหากคุณต้องการให้ nginx หรือ apache ให้บริการ
Markon

15

การให้บริการไฟล์คงที่ไม่มีส่วนเกี่ยวข้องกับแอปพลิเคชันที่มีไว้เพื่อส่งมอบเนื้อหาแบบไดนามิก วิธีที่ถูกต้องในการแสดงไฟล์แบบคงที่ขึ้นอยู่กับเซิร์ฟเวอร์ที่คุณใช้ ท้ายที่สุดเมื่อคุณเปิดใช้งานแอปคุณจะต้องเชื่อมโยงกับเว็บเซิร์ฟเวอร์ ฉันพูดได้เฉพาะ apache httpd ดังนั้นวิธีการให้บริการไฟล์แบบคงที่จึงถูกกำหนดไว้ในโฮสต์เสมือนที่คุณเชื่อมโยงกับแอปพลิเคชันของคุณผ่าน mod-wsgi นี่คือคำแนะนำที่จะแสดงวิธีแสดงแผนผังไซต์ robots.txt หรือเนื้อหาคงที่: http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide#Mounting_At_Root_Of_Site


นั่นคือคำตอบที่ฉันกำลังมองหา ขอบคุณ!
biesiad

1
แอปพลิเคชันมีขึ้นเพื่อส่งมอบเนื้อหาไดนามิกบางอย่างและแบบคงที่
Dem Pilafian

14

อีกวิธีในการส่งไฟล์แบบคงที่คือการใช้กฎ catch-all ดังนี้:

@app.route('/<path:path>')
def catch_all(path):
    if not app.debug:
        flask.abort(404)
    try:
        f = open(path)
    except IOError, e:
        flask.abort(404)
        return
    return f.read()

ฉันใช้สิ่งนี้เพื่อพยายามลดการตั้งค่าเมื่อพัฒนา ฉันได้แนวคิดมาจากhttp://flask.pocoo.org/snippets/57/

นอกจากนี้ฉันกำลังพัฒนาโดยใช้ขวดบนเครื่องแบบสแตนด์อโลน แต่ใช้กับ Apache ในเซิร์ฟเวอร์การผลิต ฉันใช้:

file_suffix_to_mimetype = {
    '.css': 'text/css',
    '.jpg': 'image/jpeg',
    '.html': 'text/html',
    '.ico': 'image/x-icon',
    '.png': 'image/png',
    '.js': 'application/javascript'
}
def static_file(path):
    try:
        f = open(path)
    except IOError, e:
        flask.abort(404)
        return
    root, ext = os.path.splitext(path)
    if ext in file_suffix_to_mimetype:
        return flask.Response(f.read(), mimetype=file_suffix_to_mimetype[ext])
    return f.read()

[...]

if __name__ == '__main__':
    parser = optparse.OptionParser()
    parser.add_option('-d', '--debug', dest='debug', default=False,
                      help='turn on Flask debugging', action='store_true')

    options, args = parser.parse_args()

    if options.debug:
        app.debug = True
        # set up flask to serve static content
        app.add_url_rule('/<path:path>', 'static_file', static_file)
    app.run()

1
โปรดทราบ - ตอนนี้มีวิธีที่ง่ายกว่าในการจัดการ ตรวจสอบการตอบกลับของฉัน
Sean McSomething

วิธีที่ยอดเยี่ยมหากคุณต้องการให้บริการหลายเส้นทาง!
Thomas Dignan

6

สิ่งนี้อาจถูกเพิ่มเข้ามาเนื่องจากคำถามนี้ถูกถาม แต่ฉันกำลังดู "helpers.py" ของกระติกน้ำและพบว่า flask.send_from_directory:

send_from_directory(directory, filename, **options)
'''
  send_from_directory(directory, filename, **options)
  Send a file from a given directory with send_file.  This
  is a secure way to quickly expose static files from an upload folder
  or something similar.
'''

... ซึ่งอ้างอิง flask.send_file:

send_file(filename_or_fp, mimetype=None, as_attachment=False, attachment_filename=None, add_etags=True, cache_timeout=43200, conditional=False)

... ซึ่งดูเหมือนจะดีกว่าสำหรับการควบคุมที่มากขึ้นแม้ว่า send_from_directory จะส่ง ** ตัวเลือกโดยตรงไปยัง send_file


3

จากเอกสารที่นี่: http://flask.pocoo.org/docs/quickstart/#static-files

เว็บแอปพลิเคชันแบบไดนามิกต้องการไฟล์แบบคงที่เช่นกัน โดยปกติจะเป็นที่มาของไฟล์ CSS และ JavaScript ตามหลักการแล้วเว็บเซิร์ฟเวอร์ของคุณได้รับการกำหนดค่าเพื่อให้บริการแก่คุณ แต่ในระหว่างการพัฒนา Flask ก็สามารถทำได้เช่นกัน เพียงสร้างโฟลเดอร์ที่เรียกว่า static ในแพ็คเกจของคุณหรือถัดจากโมดูลของคุณและจะพร้อมใช้งานที่ / static ในแอปพลิเคชัน

ในการสร้าง URL ไปยังส่วนนั้นของ URL ให้ใช้ชื่อ URL 'คงที่' พิเศษ:

url_for ('คงที่', ชื่อไฟล์ = 'style.css')

ไฟล์จะต้องถูกจัดเก็บบนระบบไฟล์เป็นแบบคงที่ / style.css


0

ฉันมีภาวะที่กลืนไม่เข้าคายไม่ออกเหมือนกัน ทำการค้นหาและพบคำตอบของฉัน (MHO):

อาจอ้างจากเอกสารประกอบ

เว็บแอปพลิเคชันแบบไดนามิกต้องการไฟล์แบบคงที่เช่นกัน โดยปกติจะเป็นที่มาของไฟล์ CSS และ JavaScript จะเป็นการดีที่เว็บเซิร์ฟเวอร์ของคุณมีการกำหนดค่าให้บริการพวกเขาสำหรับคุณ แต่ในระหว่างการพัฒนาขวดสามารถทำเช่นนั้นได้เป็นอย่างดี เพียงสร้างโฟลเดอร์ที่เรียกว่า static ในแพ็คเกจของคุณหรือถัดจากโมดูลของคุณและจะพร้อมใช้งานที่ / static ในแอปพลิเคชัน

IMHO: เมื่อแอปพลิเคชันของคุณพร้อมสำหรับการใช้งานจริงการให้บริการไฟล์แบบคงที่ควร (หรือได้รับการกำหนดค่าอย่างเหมาะสม) บนเว็บเซิร์ฟเวอร์ (nginx, apache); แต่ในระหว่างการพัฒนา Flask ได้เปิดให้ใช้งานไฟล์แบบคงที่ได้ นี่คือการช่วยให้คุณพัฒนาอย่างรวดเร็ว - ไม่จำเป็นต้องตั้งค่าเว็บเซิร์ฟเวอร์และอื่น ๆ

หวังว่าจะช่วยได้


0

ลองสิ่งนี้:

@app.route("/ProtectedFolder/<path:filename>")
@CheckUserSecurityAccessConditions
def Protect_Content(filename):
  return send_from_directory((os.path.join(os.path.dirname(__file__), 'ProtectedFolder')),filename)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.