Klicken Sie hier, um einen Überblick über unsere Bemühungen zu erhalten.
Letztes Mal Ich bin bis zu 4 fertig. Also mache ich das Original, was der ursprüngliche Zweck war. .. Wir erstellen eine Anwendung, die eine JSON-Datei liest, die eine bestimmte Konfiguration annimmt und den Inhalt visualisiert. Es gibt einige Produkte, die Konfigurationsdateien für die Arbeit in JSON ausgeben können. Daher wäre es praktisch, wenn ich sie visualisieren könnte (eventuell in der Excel-Ausgabe). Ich habe das Gefühl, dass es existiert, auch wenn ich es nicht schaffe, aber ich werde es als Übung schaffen.
Lassen Sie uns eine Anwendung erstellen, die diese Anforderung erfüllt. Eigentlich ist es einfacher, sich vorzustellen, die JSON-Datei zu verwenden, die Sie tatsächlich verwenden möchten. Da sie jedoch Informationen enthält, die nicht außerhalb des Unternehmens veröffentlicht werden können, verwenden Sie stattdessen die im Internet veröffentlichte. http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/gettingstartedguide/samples/moviedata.zip Eine JSON-Datei, die Filmtitel, Bewertungen, Genres usw. aufzeichnet.
Selbst wenn Sie es visualisieren möchten, müssen Sie zuerst verstehen, um welche Art von Struktur es sich handelt (glaube ich ...). Ich weiß nicht, was Profis tun werden, aber als Amateur verwende ich diese Chrome-Erweiterung. http://jsoneditoronline.org/
Es gibt einen Guimon, der sich fragt, ob dies für die Visualisierung in Ordnung ist, aber es besteht der Wunsch, es Excel-ähnlicher oder schließlich Excel zu machen.
Das Beispiel-JSON ist eine Datei, in der Filminformationen zusammengefasst sind. Ich möchte daraus ein Bild der folgenden Ausgabe machen.
Title | Rating | Genre | Actors |
---|---|---|---|
Prisoners | 8.2 | Crime | Hugh Jackman |
Drama | Jake Gyllenhaal | ||
Thriller | Viola Davis |
Die Anzahl der Genres und Schauspieler ist variabel.
Verwenden Sie als Umgebung dieselbe VM wie die, die bis zum [letzten Mal] verwendet wurde (http://qiita.com/KI1208/items/f4541c7355dbe57e9d6d), und teilen Sie nur die virtuelle Python-Umgebung (virtualenv) auf.
Verwenden Sie die folgende Verzeichnisstruktur.
Ich werde den Teil weglassen, der fast der gleiche ist wie beim letzten Mal.
Kürzung
Dieses Mal wird der Teil, der die Variable festlegt, in eine andere Datei getrennt.
config.py
# -*- coding: utf-8 -*-
# configuration
DATABASE = '/root/jsonparser/db/jsonparser.db'
DEBUG = True
UPLOAD_FOLDER = '/root/jsonparser/uploads/'
ALLOWED_EXTENSIONS = set(['json'])
SECRET_KEY = 'development key'
Auf die hier festgelegten Variablen kann über die py-Datei zugegriffen werden, die diese Datei wie folgt importiert hat.
Erstellen Sie die folgende SQL-Anweisung und rufen Sie sie wie zuvor aus app.py auf, um die Datenbank zu initialisieren. Der Vorgang zum Initialisieren von app.py in dieser Phase ist der gleiche wie beim letzten Mal, daher wird er weggelassen.
schema.sql
drop table if exists file_entries;
create table file_entries (
id integer primary key autoincrement,
filename string not null,
desc string,
created string
);
Fügen Sie app.py die folgende Funktion hinzu. Eine Funktion, die die Erweiterung hochgeladener Dateien überprüft.
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in app.config[
'ALLOWED_EXTENSIONS']
Als nächstes die Funktion zum Hochladen von Dateien und die Funktion zum Löschen (Eingeben) der hochgeladenen Datei.
@app.route('/', methods=['GET', 'POST'])
def inputfile():
cur = g.db.execute(
'select filename,desc,created,id from file_entries order by created desc')
entries = [dict(filename=row[0], desc=row[1], created=row[
2], id=row[3]) for row in cur.fetchall()]
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(url_for('inputfile'))
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(url_for('inputfile'))
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
current = datetime.now()
g.db.execute('insert into file_entries (filename,desc,created) values (?, ?, ?)',
[file.filename, request.form['desc'], current])
g.db.commit()
message = "File upload finished successfully."
return redirect(url_for('inputfile', message=message))
current = datetime.now().strftime('%Y/%m/%d %H:%M')
message = request.args.get('message', '')
if not message:
message = "Current time is " + current
return render_template('inputfile.html', message=message, entries=entries)
@app.route('/delete', methods=['GET', 'POST'])
def delete():
id = request.args.get('value')
g.db.execute("delete from file_entries where id = ?", [id])
g.db.commit()
return redirect(url_for('inputfile'))
Die ursprüngliche Vorlage
layout.html
<!doctype html>
<html>
<head>
<title>JSON Parser</title>
<script type="text/javascript" src="../static/js/jquery-3.1.1.min.js"></script>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
{% block head %}{% endblock %}
</head>
<div class=page>
<h1>JSON Parser</h1>
<div class=metanav>
<a href="{{ url_for('inputfile') }}">Home</a>
</div>
{% for message in get_flashed_messages() %}
<div class=flash>{{ message }}</div>
{% endfor %}
{% block body %}{% endblock %}
</div>
</html>
Bildschirm zum Hochladen, Auflisten und Löschen von Dateien.
inputfile.html
{% extends "layout.html" %}
{% block body %}
<p>{{ message }} </p>
<form action="{{ url_for('inputfile') }}" method=post class=add-entry enctype="multipart/form-data">
File: <input type="file" name="file" size="30"/><br>
Description: <input type="text" name="desc" size="30" placeholder="Description"/><br>
<input type="submit" />
</form>
<ul class=entries>
{% for entry in entries %}
<li><h2>{{ entry.filename }}</h2>
<p><a href="{{url_for('delete',value=entry.id)}}">Löschen</a></p>
Description: {{ entry.desc }}<br>
Created: {{ entry.created }}<br>
{% else %}
<li><em>Es sind noch keine Einträge vorhanden.</em>
{% endfor %}
</ul>
{% endblock %}
Laden Sie die Datei von der Aktion des Formularelements hoch. Verwenden Sie url_for, um zur Eingabedateifunktion (entsprechende URL) in app.py zu springen.
Das Stylesheet wird weggelassen, da das im Tutorial verwendete so wie es ist vorerst verwendet wird.
Wenn Sie an diesem Punkt angelangt sind, starten Sie die Anwendung und greifen Sie über den Browser darauf zu.
[root@cnenarnupgd1c jsonparser]# . env/bin/activate
(env) [root@cnenarnupgd1c jsonparser]#
(env) [root@cnenarnupgd1c jsonparser]# python app.py
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger pin code: 173-472-212
Wenn Sie die Datei hochladen,
Bis zu diesem Punkt ist OK.
Der Kick ist der Bildschirm, auf dem die Liste der zuvor erstellten hochgeladenen Dateien angezeigt wird. Fügen Sie dem Bildschirm einen Link mit dem Namen "Configure Confirmation" hinzu und überspringen Sie ihn zusammen mit dem Namen der Zieldatei zur Funktion "output".
inputfile.html(Teil)
<ul class=entries>
{% for entry in entries %}
<li><h2>{{ entry.filename }}</h2>
<p><a href="{{url_for('output',value=entry.filename)}}">Konfigurationsprüfung</a></p>
<p><a href="{{url_for('delete',value=entry.id)}}">Löschen</a></p>
Description: {{ entry.desc }}<br>
Created: {{ entry.created }}<br>
{% else %}
<li><em>Es sind noch keine Einträge vorhanden.</em>
{% endfor %}
</ul>
Die empfangene Funktion ist wie folgt. Lesen Sie die JSON-Datei basierend auf dem als Wert übergebenen Dateinamen, übergeben Sie sie zum Parsen an das Modul und übergeben Sie das zurückgegebene Objekt an die Vorlage.
app.py(Teil)
from parse_json import parse_json
@app.route('/output')
def output():
fname = request.args.get('value').replace(' ','_')
fpath = app.config['UPLOAD_FOLDER'] + fname
jsonfile = open(fpath,'r')
config = json.load(jsonfile)
output = parse_json(config)
return render_template('output.html', entries=output)
Als nächstes folgt das Modul zum Parsen.
parse_json.py
import sys
def parse_json(config):
# Initialize array
# Create (num of movie) * empty {}
arr = []
for i in range(len(config)):
try:
arr[i].append({})
except IndexError:
arr.append({})
except:
print 'Unexpected Error:',sys.exc_info()[0]
# Populate arr
for idx,movie in enumerate(config):
try:
arr[idx].update({'title': movie.get('title')})
arr[idx].update({'rank': movie.get('info').get('rank')})
arr[idx].update({'genres': movie.get('info').get('genres')})
arr[idx].update({'actors': movie.get('info').get('actors')})
if movie.get('info').get('genres') and movie.get('info').get('actors'):
arr[idx].update({'rowspan': max(len(movie.get('info').get('genres')),len(movie.get('info').get('actors')))})
elif not movie.get('info').get('genres') and movie.get('info').get('actors'):
arr[idx].update({'rowspan': len(movie.get('info').get('actors'))})
elif movie.get('info').get('genres') and not movie.get('info').get('actors'):
arr[idx].update({'rowspan': len(movie.get('info').get('genres'))})
else:
arr[idx].update({'rowspan': 1})
except:
print 'Unexpected Error:', sys.exc_info()[0]
pass
return arr
Um ehrlich zu sein, denke ich, dass es möglich ist, mit Flask-Code (auf HTML) auf dieser Ebene zu verarbeiten, aber ich denke später darüber nach. Außerdem wird unterwegs eine Variable namens rowspan berechnet. Diese Variable gibt jedoch an, wie viele Zeilen für jeden Film erforderlich sind.
Klicken Sie hier, um eine Vorlage zum Übergeben des generierten Objekts anzuzeigen.
output.html
{% extends "layout.html" %}
<h1>Movies</h1>
{% block body %}
<table ~~~ style="table-layout:fixed;width:100%;" border = "3">
<colgroup>
<col style="width:25%;">
<col style="width:25%;">
<col style="width:25%;">
<col style="width:25%;">
</colgroup>
<tr bgcolor="skyblue">
<td ~~~ style="word-wrap:break-word;">Title</td>
<td ~~~ style="word-wrap:break-word;">Rank</td>
<td ~~~ style="word-wrap:break-word;">Genres</td>
<td ~~~ style="word-wrap:break-word;">Actors</td>
</tr>
{% for entry in entries %}
{% for i in range(entry.rowspan) %}
<tr>
{% if i == 0 %}
<td ~~~ style="word-wrap:break-word;" rowspan = "{{ entry.rowspan }}">{{ entry.title }}</td>
<td ~~~ style="word-wrap:break-word;" rowspan = "{{ entry.rowspan }}">{{ entry.rank }}</td>
{% endif %}
{% if entry.genres[i] %}
<td ~~~ style="word-wrap:break-word;">{{ entry.genres[i] }}</td>
{% else %}
<td ~~~ style="word-wrap:break-word;" bgcolor="black">Empty</td>
{% endif %}
{% if entry.actors[i] %}
<td ~~~ style="word-wrap:break-word;">{{ entry.actors[i] }}</td>
{% else %}
<td ~~~ style="word-wrap:break-word;" bgcolor="black">Empty</td>
{% endif %}
</tr>
{% endfor %}
{% else %}
<tr><td ~~~ style="word-wrap:break-word;" columnspan="4">No entry here.</td></tr>
{% endfor %}
</table>
{% endblock %}
Zeigen Sie bei Einträgen, für die 4 Zeilen erforderlich sind, Titel und Rang zusammen in 4 Zeilen an. Füllen Sie die restlichen Zellen aus.
Außerdem ist die Zellenbreite so festgelegt, dass lange Zeichenfolgen umbrochen werden. Es bezieht sich auf Folgendes. http://qiita.com/n_s_y_m/items/cb29d730e63772b02475
Die Ausgabe wird wie folgt sein. Unabhängig von der Anzahl der Elemente befindet es sich in der Nähe des Bildes.
Eigentlich wäre es schön, nach Spalten sortieren zu können, aber sobald dies erledigt ist. Die gesamte Quelle usw. werden unten veröffentlicht. https://github.com/KI1208/jsonparser.git
Auf den ersten Blick gibt es derzeit viele Probleme und Anfragen, aber ich werde meine Augen schließen und es zu einem zukünftigen Thema machen.
Recommended Posts