Использование одного декоратора вместо нескольких? «Один ко многим» и «много к одному»? - PullRequest
0 голосов
/ 13 января 2019

Я пытаюсь создать простую веб-страницу следующим образом, чтобы получить фотографии профиля студентов. Мой вопрос ниже - просто простой пример, чтобы задать мой вопрос и понять логику.

Допустим; У меня есть три класса, названные Class_A2E, Class_F2J и Class_K2O. В школе это могут студенты 1 курса, 2 курса и 3 курса. Каждый год студенты делятся на 5 классов, названных как A-E [таким образом, A, B, C, D, E] (1-й год), F-J (2-й год) и K-O (3-й год). Я хочу показать фотографию ученика в формате png и дать ссылку в качестве опции для загрузки в виде файла PDF (который имеет высокое качество).

Как видно, у меня есть такой же декоратор, но с разными именами для разработки такой веб-страницы. Что я хотел бы сделать; используя один декоратор для всех.

другая проблема: после печати изображения я хочу вернуться на ту же страницу класса, чтобы найти другого ученика. Тем не менее, он всегда дает ссылку на 1-й год.

HTML-файлы находятся в папке «Шаблоны». main.css находится в «статической» папке. Папка «static» содержит изображения png в png_files и изображения pdf в папке pdf_files.

Вот мои коды, как показано ниже:

# run.py
from flask import Flask, render_template, request

app = Flask(__name__)
app.config['SECRET_KEY'] = "7642e9aed5740e5ggca2de92ae021de5"

@app.route("/")
@app.route("/my_classes_A2E")
def my_classes_A2E():
    return render_template("my_classes_A2E.html", title= "my_classes_A2E", class_ids=[{'name':'ClassA'},{'name':'ClassB'},{'name':'ClassC'},{'name':'ClassD'},{'name':'ClassE'}])

@app.route("/", methods = ['GET','POST'])
def get_input_and_print_imgs_A2E():
    class_id = request.form.get('class_id_select')
    student_name = request.form["student_name"]
    return render_template("print_student_profilepics.html",class_id=class_id, student_name=student_name, html_link="my_classes_A2E", html_title="1stYear")

@app.route("/my_classes_F2J")
def my_classes_F2J():
    return render_template("my_classes_F2J.html", title= "my_classes_F2J", class_ids=[{'name':'ClassF'},{'name':'ClassG'},{'name':'ClassH'},{'name':'ClassI'},{'name':'ClassJ'}])

@app.route("/", methods = ['GET','POST'])
def get_input_and_print_imgs_F2J():
    class_id = request.form.get('class_id_select')
    student_name = request.form["student_name"]
    return render_template("print_student_profilepics.html",class_id=class_id, student_name=student_name, html_link="my_classes_F2J", html_title="2ndYear")

@app.route("/my_classes_K2O")
def my_classes_K2O():
    return render_template("my_classes_K2O.html", title= "my_classes_K2O", class_ids=[{'name':'ClassK'},{'name':'ClassL'},{'name':'ClassM'},{'name':'ClassN'},{'name':'ClassO'}])

@app.route("/", methods = ['GET','POST'])
def get_input_and_print_imgs_K2O():
    class_id = request.form.get('class_id_select')
    student_name = request.form["student_name"]
    return render_template("print_student_profilepics.html",class_id=class_id, student_name=student_name, html_link="my_classes_K2O", html_title="3rdYear")


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

## ANOTHER SOLUTION: the above code in run.py can be edited as below and it will also works fine. ###

from flask import Flask, render_template, request

app = Flask(__name__)
app.config['SECRET_KEY'] = "7642e9aed5740e5ggca2de92ae021de5"

@app.route("/")
@app.route("/my_classes_A2E/")
def my_classes_A2E():
    return render_template("my_classes_A2E.html", title= "my_classes_A2E", class_ids=[{'name':'ClassA'},{'name':'ClassB'},{'name':'ClassC'},{'name':'ClassD'},{'name':'ClassE'}])

@app.route("/my_classes_A2E/get_input_and_print_imgs_A2E", methods = ['GET','POST'])
def get_input_and_print_imgs_A2E():
    class_id = request.form.get('class_id_select')
    student_name = request.form["student_name"]
    return render_template("print_student_profilepics.html",class_id=class_id, student_name=student_name, html_link="my_classes_A2E", html_title="1stYear")

@app.route("/my_classes_F2J/")
def my_classes_F2J():
    return render_template("my_classes_F2J.html", title= "my_classes_F2J", class_ids=[{'name':'ClassF'},{'name':'ClassG'},{'name':'ClassH'},{'name':'ClassI'},{'name':'ClassJ'}])

@app.route("/my_classes_F2J/get_input_and_print_imgs_F2J", methods = ['GET','POST'])
def get_input_and_print_imgs_F2J():
    class_id = request.form.get('class_id_select')
    student_name = request.form["student_name"]
    return render_template("print_student_profilepics.html",class_id=class_id, student_name=student_name, html_link="my_classes_F2J", html_title="1stYear")

@app.route("/my_classes_K2O/")
def my_classes_K2O():
    return render_template("my_classes_K2O.html", title= "my_classes_K2O", class_ids=[{'name':'ClassK'},{'name':'ClassL'},{'name':'ClassM'},{'name':'ClassN'},{'name':'ClassO'}])

@app.route("/my_classes_K2O/get_input_and_print_imgs_K2O", methods = ['GET','POST'])
def get_input_and_print_imgs_K2O():
    class_id = request.form.get('class_id_select')
    student_name = request.form["student_name"]
    return render_template("print_student_profilepics.html",class_id=class_id, student_name=student_name, html_link="my_classes_K2O", html_title="1stYear")


if __name__ == "__main__":
    app.run(debug= True)
#
########## this is layout.html as template for all other html fies ######
<!DOCTYPE html>
<html>
    <head>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
        <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">

        {% if title %}
            <title> MY WEB PAGE - {{ title }} </title>
        {% else %}
            <title> MY WEB PAGE </title>
        {% endif %}

        <header class="site-header">
            <nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
                <div class="container">
                    <a style="color:#z00000" class="navbar-brand mr-4" href="/my_classes_A2E"><b>1stYear</b></a>
                    <a style="color:#z00000" class="navbar-brand mr-4" href="/my_classes_F2J"><b>2ndYear</b></a>
                    <a style="color:#z00000" class="navbar-brand mr-4" href="/my_classes_K2O"><b>3rdYear</b></a>
                    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
                        <span class="navbar-toggler-icon"></span>
                    </button>               
                </div>
            </nav>
        </header>

    </head>
    <body>
        <div class="container">
            {% block content %}
            {% endblock %}
        </div>
        <!-- Optional JavaScript -->
        <!-- jQuery first, then Popper.js, then Bootstrap JS -->
        <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>
    </body>
</html>

################ my_classes_A2E.html #######################
{% extends "layout.html" %}
{% block content %}
    <h1 style="color:#f00000"> This page is under construction and will be updated soon! </h1>
    <form style="width: 50px !important; min-width: 100px; max-width: 100px;" name="pass_class_idt" id="pass_class_id" action="." method="POST">
        <label>Class ID 1stYear </label>
        <select name="class_id_select" class="selectpicker form-control">
          {% for class_id in class_ids %}
            <option value="{{ class_id.name }}">{{ class_id.name }}</option>
          {% endfor %}
        </select>
        <label> Student Name in1stYear :</label>
        <input type="text" name="student_name">
        <input type="submit" value="submit">
    </form>
{% endblock %}

################ my_classes_F2J.html #######################
{% extends "layout.html" %}
{% block content %}
    <h1 style="color:#f00000"> This page is under construction and will be updated soon! </h1>
    <form style="width: 50px !important; min-width: 100px; max-width: 100px;" name="pass_class_id" id="pass_class_id" action="." method="POST">
        <label>Class ID 2ndYear </label>
        <select name="class_id_select" class="selectpicker form-control">
          {% for class_id in class_ids %}
            <option value="{{ class_id.name }}">{{ class_id.name }}</option>
          {% endfor %}
        </select>
        <label> Student Name in 2ndYear:</label>
        <input type="text" name="student_name">
        <input type="submit" value="submit">
    </form>
{% endblock %}

################ my_classes_K2O.html #######################
{% extends "layout.html" %}
{% block content %}
    <h1 style="color:#f00000"> This page is under construction and will be updated soon! </h1>
    <form style="width: 50px !important; min-width: 100px; max-width: 100px;" name="pass_class_id" id="pass_class_id" action="." method="POST">
        <label> Class ID 3rdYear </label>
        <select name="class_id_select" class="selectpicker form-control">
          {% for class_id in class_ids %}
            <option value="{{ class_id.name }}">{{ class_id.name }}</option>
          {% endfor %}
        </select>
        <label> Student Name in 3rdYear:</label>
        <input type="text" name="student_name">
        <input type="submit" value="submit">
    </form>
{% endblock %}


################ print_student_profilepics.html #######################

{% extends "layout.html" %}
{% block content %}
    <h1 style="color:#f00000"> This page is under construction and will be updated soon! </h1>
    <div class="container"> 
        <embed src="/static/png_files/{{ class_id }}_{{ student_name }}_profilepics.png" width = "700" height= "700">
    </div>  
    <p style="margin-left:23rem;"> <b> Download as: <a href="/static/pdf_files/{{ class_id }}_{{ student_name }}_profilepics.pdf" class="button"> PDF </b></a> <small style="color:#f00000;"> (for High Quality) </small> </p>
    <p style="margin-left:23rem;"> <b> Go Back To     : <a  href="{{ html_link }}"> {{ html_title }} </b></a> </p>
{% endblock %}

1 Ответ

0 голосов
/ 13 января 2019

Параметризация маршрутов

При определении маршрута колбы синтаксис < > позволяет определить переменный строковый параметр URL, который позаботится обо всех маршрутах, записанных в этой форме:

Например:

@app.route("/my-classes/<class_group>")
def my_classes(class_group):
    ...

Будет ли перенаправлять URL-адреса как /my-classes/A2E через функцию my_classes(class_group) с параметром class_group, установленным в str: "A2E". Я обновил ваш фактический исходный шаблон URL, /my_classes_A2E, потому что это более стандартный способ маршрутизации, хотя вы можете добиться того же эффекта с /my_classes_<class_group>, если хотите сохранить свой. Кроме того, более обычным является написание маршрутов с дефисами - вместо подчеркивания _ (см. URL этой ссылки на переполнение стека!)

Приоритет маршрутов

другая проблема: после печати изображения я хочу вернуться на ту же страницу класса, чтобы найти другого ученика. Тем не менее, он всегда дает ссылку на 1-й год.

Относительно этого примечания обратите внимание, что вы определили те же маршруты URL для ваших 3 групп классов!

@app.route("/", methods = ['GET','POST'])
def get_input_and_print_imgs_A2E():
    ...
@app.route("/", methods = ['GET','POST'])
def get_input_and_print_imgs_F2J():
    ...
@app.route("/", methods = ['GET','POST'])
def get_input_and_print_imgs_K2O():
    ...

Несмотря на то, что flask не вызывает никаких ошибок при запуске сервера, только первая функция будет обрабатывать ваш / URL-запрос, который объясняет, почему вы получаете только ссылки на 1-й год.

Завершение

Возможно, вам будет интересно сначала определить словарь, который будет содержать логику ваших классов: это первые 3 словаря. Учитывая это, вы можете сократить 2 * 3 маршрута до 2 маршрутов, потому что вся логика «группы» будет разложена.


# run.py
from flask import Flask, render_template, request

app = Flask(__name__)
app.config['SECRET_KEY'] = "7642e9aed5740e5ggca2de92ae021de5"

class_group_dict = {
    "A2E": [{'name': 'ClassA'}, {'name': 'ClassB'}, {'name': 'ClassC'}, {'name': 'ClassD'}, {'name': 'ClassE'}],
    "F2J": [{'name': 'ClassF'}, {'name': 'ClassG'}, {'name': 'ClassH'}, {'name': 'ClassI'}, {'name': 'ClassJ'}],
    "K2O": [{'name': 'ClassK'}, {'name': 'ClassL'}, {'name': 'ClassM'}, {'name': 'ClassN'}, {'name': 'ClassO'}]
}

class_group_to_year = {
    "A2E": "1stYear",
    "F2J": "2ndYear",
    "K2O": "3rdYear"
}

class_id_to_class_year = {
    class_dict["name"]: class_year for class_year, list_class in class_group_dict.items()
    for class_dict in list_class
}

@app.route("/my-classes/<class_group>/get-input-and-print-imgs", methods=['GET', 'POST'])
def get_input_and_print_imgs(class_group):  # test
    class_id = request.form.get('class_id_select')
    student_name = request.form["student_name"]
    return render_template("print_student_profilepics.html",
                           class_id=class_id, student_name=student_name,
                           html_link=f"my_classes_{class_id_to_class_year[class_group]}",
                           html_title=class_group_to_year[class_group])


@app.route("/my-classes/<class_group>")
def my_classes(class_group):  # class_group: one of ["A2E", "F2J",  "K2O"]
    return render_template(f"my_classes_{class_group}.html",
                           title=f"my_classes_{class_group}",
                           class_ids=class_group_dict[class_group])

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

Заключительные ноты

Я не позволил себе сменить имена .html, но соглашения предложили бы вместо этого использовать дефисы. Также для ясности, возможно, было бы лучше выбрать одно поле именования для class_name / id (то есть. ClassA, classB, ect ...), поскольку оно упоминается обоими.

Обновление HTML-файлов

Вам нужно изменить поле действия тега <form> в my_classes_A2E, my_classes_F2J, my_classes_K2O, чтобы указать хороший маршрут, т.е. это будет для my_classes_A2E

<form style="width: 50px !important; min-width: 100px; max-width: 100px;" name="pass_class_idt" id="pass_class_id" action="/my-classes/A2E/get-input-and-print-imgs" method="POST">
...