這是我在這個論壇上提出的第一個問題。我非常渴望找到解決方案......希望我能向你們學習。我有一個解決方案,但是在瀏覽器視窗中發布整個目錄樹并知道檔案名,這不是我想要的。
現在我找到了這樣的代碼片段并對其進行了一些更改。它的生成器運算式,我認為 Jinja2 不支持:
import os
path = r"C:/Users/add706/Documents/NRL_webseite/website/static/uploads"
def get_files(path):
for file in os.listdir(path):
if os.path.isfile(os.path.join(path, file)):
yield file
for file in get_files(path):
print(file)
輸出在路徑內給了我 3 個檔案: 1.jpeg postgre.jpeg winrar-x64-610d.exe
我正在嘗試制作一個串列并將其傳遞給 JINJA2。我已經創建了一個模板,但是不知何故,當我運行燒瓶時,我無法列出檔案并且列印功能為空。由于 3 天我坐在上面,甚至沒有錯誤訊息,這可以幫助我。
這是我最初對 auth.py 的看法(庫的匯入很好,這里沒有列出):
path = r"C:/Users/add706/Documents/NRL_webseite/website/static/uploads"
@auth.route('/', methods = ['GET', 'POST'])
def get_files(path):
for file in os.listdir(path):
if os.path.isfile(os.path.join(path, file)):
return (os.listdir(path))
files=[]
for file in get_files(path):
files.append(file)
print(files)
return render_template('home.html', files=get_files(path))
This is my original outtake of home.html template (which was %extended%), looping through the returned files ( I wish to...):
<!-- download Folder-->
<div align="center">
<image src="{{ url_for('static', filename='uploads/postgre.jpeg')}}">
</ul>
{% for file in files %}
<li class="collection-item"><a href="#">{{ file }}</a></li>
{% endfor %}
</ul>
</div>
The question is now: What do I have to change in my both files that I can see the 3 files on my local webpage (http://127.0.0.1:5000/)? I would like to list them and make them clickable, so while clicking, the file can be downloaded as attachment. Second thing is, to list them with upload time. THird thing is, that the download process, let a window popping up, which asks me "DO you wish to download (filename). To visualize my problem, I uploaded an image and drew red boxes. Thanks in regard for every help out there.
Image link: (https://imgur.com/a/z4l8zH2)
我找到了這篇文章,它在我的腳本中說樹是未定義的(使用 flask 列出目錄中的檔案),所以我放棄了它。
uj5u.com熱心網友回復:
您確實可以在 jinja2 中使用生成器。
我寫的例子應該能滿足你的需要。
它將目錄中的檔案顯示為串列。每個條目都分配有其大小和上傳時間。uploads 檔案夾位于實體檔案夾內,用于將檔案與應用程式分開。
我使用燒瓶時刻來顯示正確的時間。這使用moment.js并在客戶端的相應時區顯示時間戳。
我使用自定義 Jinja2過濾器來顯示檔案大小。
如果單擊檔案進行下載,則會打開一個要求確認的對話框。這是使用 JavaScript 完成的。
玩得開心實作你的目標。
燒瓶(app.py)
from flask import (
Flask,
render_template,
send_from_directory
)
from flask_moment import Moment
from datetime import datetime
import os
def byte_units(value, units=-1):
UNITS=('Bytes', 'KB', 'MB', 'GB', 'TB', 'EB', 'ZB', 'YB')
i=1
value /= 1000.0
while value > 1000 and (units == -1 or i < units) and i 1 < len(UNITS):
value /= 1000.0
i = 1
return f'{round(value,3):.3f} {UNITS[i]}'
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.path.join(app.instance_path, 'uploads')
app.jinja_env.filters.update(byte_units = byte_units)
moment = Moment(app)
try:
os.makedirs(app.config['UPLOAD_FOLDER'])
except:
pass
def get_files(target):
for file in os.listdir(target):
path = os.path.join(target, file)
if os.path.isfile(path):
yield (
file,
datetime.utcfromtimestamp(os.path.getmtime(path)),
os.path.getsize(path)
)
@app.route('/')
def index():
files = get_files(app.config['UPLOAD_FOLDER'])
return render_template('index.html', **locals())
@app.route('/download/<path:filename>')
def download(filename):
return send_from_directory(
app.config['UPLOAD_FOLDER'],
filename,
as_attachment=True
)
HTML (模板/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Index</title>
{{ moment.include_moment() }}
</head>
<body>
<table style="width:40%; margin:auto; table-layout: fixed;">
{% for filename, mtime, size in files -%}
<tr>
<td><a href="{{ url_for('download', filename=filename) }}" download>{{ filename }}</a></td>
<td>{{ moment(mtime, local=False).format('DD.MM.YYYY HH:mm') }}</td>
<td style="text-align:right;">{{ size | byte_units }}</td>
</tr>
{% endfor -%}
</table>
<script type="text/javascript">
(() => {
const elems = document.querySelectorAll('a[href][download]');
elems.forEach(elem => {
elem.addEventListener('click', evt => {
const isDonwload = window.confirm('Would you like to download this file?');
if (!isDonwload) { evt.preventDefault(); }
});
});
})();
</script>
</body>
</html>
I've added my code to your project. It should work now.
You should work on structuring your project so that you can find your way around the code more easily. I cannot relieve you of this task in this context.
(website/init.py)
from flask import Flask
from flask_login import LoginManager
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
import os
DB_NAME = "database.db"
db = SQLAlchemy()
moment = Moment()
def byte_units(value, units=-1):
UNITS=('Bytes', 'KB', 'MB', 'GB', 'TB', 'EB', 'ZB', 'YB')
i=1
value /= 1000.0
while value > 1000 and (units == -1 or i < units) and i 1 < len(UNITS):
value /= 1000.0
i = 1
return f'{round(value,3):.3f} {UNITS[i]}'
def create_app():
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY=b'your secret here',
SQLALCHEMY_DATABASE_URI='sqlite:///' os.path.join(app.instance_path, DB_NAME),
SQLALCHEMY_TRACK_MODIFICATIONS=False,
UPLOAD_FOLDER=os.path.join(app.instance_path, 'uploads')
)
app.jinja_env.filters.update(byte_units = byte_units)
try:
os.makedirs(app.config['UPLOAD_FOLDER'])
except:
pass
db.init_app(app)
moment.init_app(app)
from .models import User, Note
create_database(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
@login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
from .views import views
from .auth import auth
app.register_blueprint(auth, url_prefix='/')
app.register_blueprint(views, url_prefix='/')
return app
def create_database(app):
if not os.path.exists(os.path.join(app.instance_path, DB_NAME)):
db.create_all(app=app)
print('Created Database!')
(website/auth.py)
import os
import json
from . import db
from .models import User
from flask import (
Blueprint,
flash,
redirect,
render_template,
request,
url_for
)
from flask_login import login_user, login_required, logout_user, current_user
auth = Blueprint('auth', __name__)
@auth.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form.get('email')
password = request.form.get('password')
user = User.query.filter_by(email=email).first()
if user:
if check_password_hash(user.password, password):
flash('Logged in successfully!', category='success')
login_user(user, remember=True)
return redirect(url_for('views.home'))
else:
flash('Incorrect password, try again.', category='error')
else:
flash('Email does not exist.', category='error')
return render_template('login.html', user=current_user)
@auth.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('auth.login'))
@auth.route('/sign-up', methods=['GET', 'POST'])
def sign_up():
if request.method == 'POST':
email = request.form.get('email')
first_name = request.form.get('firstName')
password1 = request.form.get('password1')
password2 = request.form.get('password2')
user = User.query.filter_by(email=email).first()
if user:
flash('Email already exists.', category='error')
elif len(email) < 4:
flash('Email must be greater than 3 characters.', category='error')
elif len(first_name) < 2:
flash('First name must be greater than 1 character.', category='error')
elif password1 != password2:
flash('Passwords don\'t match.', category='error')
elif len(password1) < 7:
flash('Password must be at least 7 characters.', category='error')
else:
new_user = User(email=email, first_name=first_name, password=generate_password_hash(
password1, method='sha256'))
db.session.add(new_user)
db.session.commit()
login_user(new_user, remember=True)
flash('Account created!', category='success')
return redirect(url_for('views.home'))
return render_template('sign_up.html', user=current_user)
(website/views.py)
from . import db
from .models import Note
from flask import Blueprint, current_app, flash, jsonify, render_template, request
from flask_login import login_required, current_user
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
import os
views = Blueprint('views', __name__)
@views.route('/', methods=['GET', 'POST'])
@login_required
def home():
if request.method == 'POST':
note = request.form.get('note')
if len(note) < 1:
flash('Note is too short!', category='error')
else:
new_note = Note(data=note, user_id=current_user.id)
db.session.add(new_note)
db.session.commit()
flash('Note added!', category='success')
user=current_user
files = get_files(current_app.config['UPLOAD_FOLDER'])
return render_template('home.html', **locals())
@views.route('/delete-note', methods=['POST'])
def delete_note():
note = json.loads(request.data)
noteId = note['noteId']
note = Note.query.get(noteId)
if note:
if note.user_id == current_user.id:
db.session.delete(note)
db.session.commit()
return jsonify({})
# ---
@views.route('/about')
def about():
return render_template('about.html', user=None)
# ---
@views.route('/upload', methods = ['GET', 'POST'])
def uploadfile():
upload_folder = current_app.config['UPLOAD_FOLDER']
if request.method == 'POST': # check if the method is post
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file'] # get the file from the files object
if file.filename == '':
flash('No selected file')
return redirect(request.url)
file.save(os.path.join(
upload_folder ,
secure_filename(file.filename))) # this will secure the file
flash('file uploaded successfully') # Display this message after uploading
return redirect('/')
def get_files(target):
for file in os.listdir(target):
path = os.path.join(target, file)
if os.path.isfile(path):
yield (
file,
datetime.utcfromtimestamp(os.path.getmtime(path)),
os.path.getsize(path)
)
@views.route('/download/<path:filename>')
def download(filename):
return send_from_directory(
app.config['UPLOAD_FOLDER'],
filename,
as_attachment=True
)
(templates/base.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3 Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
crossorigin="anonymous"
/>
<title>{% block title %}Home{% endblock %}</title>
{{ moment.include_moment() }}
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<button
class="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbar"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbar">
<div class="navbar-nav">
{% if user.is_authenticated %}
<a class="nav-item nav-link" id="home" href="/">Home</a>
<a class="nav-item nav-link" id="logout" href="/logout">Logout</a>
{% else %}
<a class="nav-item nav-link" id="login" href="/login">Login</a>
<a class="nav-item nav-link" id="signUp" href="/sign-up">Sign Up</a>
<a class="nav-item nav-link" id="über Uns" href="/about">über uns</a>
{% endif %}
</div>
</div>
</nav>
{% with messages = get_flashed_messages(with_categories=true) %} {% if
messages %} {% for category, message in messages %} {% if category ==
'error' %}
<div class="alert alert-danger alter-dismissable fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">×</span>
</button>
</div>
{% else %}
<div class="alert alert-success alter-dismissable fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %} {% endfor %} {% endif %} {% endwith %}
<div class="container">{% block content %} {% endblock %}</div>
<script
src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"
></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5 76PVCmYl"
crossorigin="anonymous"
></script>
<script
type="text/javascript"
src="{{ url_for('static', filename='index.js') }}"
></script>
</body>
</html>
(templates/home.html)
{% extends "base.html" -%}
{% block title %}Home{% endblock -%}
{% block content -%}
<h1 align="center">Notes</h1>
<ul class="list-group list-group-flush" id="notes">
{% for note in user.notes %}
<li class="list-group-item">
{{ note.data }}
<button type="button" class="close" onClick="deleteNote({{ note.id }})">
<span aria-hidden="true">×</span>
</button>
</li>
{% endfor %}
</ul>
<form method="POST">
<textarea name="note" id="note" class="form-control"></textarea>
<br />
<div align="center">
<button type="submit" class="btn btn-primary">Add Note</button>
</div>
</form>
<br>
<br>
<br>
<br>
<!-- upload Folder-->
<div class="container">
<div class="row">
<div class="col">
<h1 align="center">Datei Upload</h1>
<hr>
<form
action="http://localhost:5000/upload"
method="POST"
enctype="multipart/form-data">
<input type="file" name="file" />
<button type="submit" class="btn btn-primary">Upload</button>
</form>
</div>
</div>
</div>
<br>
<br>
<br>
<br>
<!-- download Folder-->
<div align="center">
<image src="{{ url_for('static', filename='uploads/postgre.jpeg')}}">
</div>
<table style="width:40%; margin:auto; table-layout: fixed;">
{% for filename, mtime, size in files -%}
<tr>
<td><a href="{{ url_for('views.download', filename=filename) }}" download>{{ filename }}</a></td>
<td>{{ moment(mtime, local=False).format('DD.MM.YYYY HH:mm') }}</td>
<td style="text-align:right;">{{ size | byte_units }}</td>
</tr>
{% endfor -%}
</table>
<script type="text/javascript">
(() => {
const elems = document.querySelectorAll('a[href][download]');
elems.forEach(elem => {
elem.addEventListener('click', evt => {
const isDonwload = window.confirm('Would you like to download this file?');
if (!isDonwload) { evt.preventDefault(); }
});
});
})();
</script>
{% endblock -%}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/437670.html
上一篇:無法將空值回傳到vue上的輸入框
