Используйте python jinja для автоматического увеличения идентификатора изображения из SQL-Alchemy-DB, обслуживаемого в html через флягу

Я пытаюсь создать галерею.html, которая изменяет поведение изображения по идентификатору изображения, например, id="lightbox-1", id="lightbox-2", id="lightbox-3", а поведение галереи изменяется в соответствии с css, это хорошо работает с использованием путей к файлам в качестве примера кода ниже:

 <div id = "gallery">
      <div><img src = "images/12.jpg"/><a href = "#lightbox-1">512</a></div>
      <div><img src = "images/13.jpg"/><a href = "#lightbox-2">513</a></div>
      ...

и

<div class = "lightbox" id = "lightbox-1">
      <div class = "content"><img src = "images/12b.jpg"/>
        <div class = "title">No. <b>512</b> from Picsum</div><a class = "close" href = "#gallery"></a>
      </div>
    </div>

Однако я получаю изображения из базы данных sql-alchemy и использую этот метод для получения изображений из БД, Изображения успешно извлекаются, но расположение бессистемно, и я решил, что идентификационный номер не увеличивается, поэтому я пытаюсь программно увеличить идентификационный номер. Вот мой код:

<h5>Gallery</h5>
    {% set n = 1 %}
    {% for image in image_list %}
    <div id = "gallery">
      <div>
        <img src = "data:;base64,{{ image }}"/>
        <a href = "#lightbox-{{n}}">{{n}}</a>
 
      </div>

    </div>

    <div class = "lightbox" id = "lightbox-{{n}}">
      <div class = "content"><img src = "data:;base64,{{ image }}"/>
      </div>
    </div>
    {% set n = n+1 %}
    {% endfor %}

Проще говоря, я хочу имитировать это поведение и дизайн, используя flask для обслуживания html и sql-алхимии для изображений. На данный момент я могу обслуживать и получать изображения, но не могу воспроизвести поведение css. заранее спасибо

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что вы выполняете итерацию не в том месте и получаете другую структуру, которая не соответствует таблице стилей.

Чтобы получить текущий индекс в текущей итерации, я рекомендую вам использовать loop.index. Поэтому создание и увеличение собственной переменной не требуется.

Колба (./app.py)
from flask import (
    Flask, 
    current_app, 
    redirect, 
    render_template, 
    request, 
    url_for
)
from flask_sqlalchemy import SQLAlchemy
import base64

app = Flask(__name__)
app.config.from_mapping(
    SQLALCHEMY_DATABASE_URI='sqlite:///example.db',
    SQLALCHEMY_TRACK_MODIFICATIONS=False,
    UPLOAD_EXTENSIONS=('jpg',)
)
db = SQLAlchemy(app)

class GalleryImage(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    mime = db.Column(db.String, nullable=False)
    data = db.Column(db.LargeBinary(), nullable=False)

    @property
    def b64encoded(self):
        return base64.b64encode(self.data).decode('ascii')

with app.app_context():
    db.create_all()

@app.route('/')
def index():
    images = GalleryImage.query.all()
    return render_template('index.html', **locals())

def allowed_file(filename):
    allowed_extensions = current_app.config.get('UPLOAD_EXTENSIONS', [])
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in allowed_extensions

@app.route('/upload', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        files = request.files.getlist('file[]')
        for file in files: 
            if file.filename != '' and allowed_file(file.filename):
                image = GalleryImage(
                    mime=file.mimetype, 
                    data=file.read()
                )
                db.session.add(image)
        try:
            db.session.commit()
        except: 
            db.session.rollback()
        return redirect(url_for('.index'))
    return render_template('upload.html')
HTML-шаблон (./templates/upload.html)
<!DOCTYPE html>
<html>
<head>
    <meta charset = "utf-8">
    <meta name = "viewport" content = "width=device-width, initial-scale=1">
    <title>Upload</title>
</head>
<body>
    <form method = "post" enctype = "multipart/form-data">
        <input type = "file" name = "file[]" accept = "image/jpeg" multiple />
        <button type = "submit">Upload</button>
    </form>
</body>
</html>
HTML-шаблон (./templates/index.html)
<!DOCTYPE html>
<html>
<head>
    <meta charset = "utf-8">
    <meta name = "viewport" content = "width=device-width, initial-scale=1">
    <title>Index</title>
    <link rel = "stylesheet" type = "text/css" href = "{{ url_for('static', filename='css/main.css') }}">
</head>
<body>

    <h5>Gallery</h5>
    
    <div id = "gallery">
        {% for img in images -%}
        <div id = "gallery-thumb-{{loop.index}}">
            <img src = "data:;base64,{{ img.b64encoded }}" />
            <a href = "#lightbox-{{ loop.index }}">{{ loop.index }}</a>
        </div>
        {% endfor -%}
    </div>

    {% for img in images -%}
    <div class = "lightbox" id = "lightbox-{{ loop.index }}">
        <div class = "content">
            <img src = "data:;base64,{{ img.b64encoded }}" />
            <a class = "close" href = "#gallery-thumb-{{loop.index}}"></a>
        </div>
    </div> 
    {% endfor -%}

</body>
</html>
CSS (./static/css/main.css)
* {
    box-sizing: border-box;
}
body {
    margin: 5px;
    position: relative;
}
#gallery {
    display: grid;
    /*  height: calc(100vh - 10px);*/ /* !!! */
    grid-template: repeat(6, 1fr) / repeat(6, 1fr);
    grid-gap: 0.5em;
}
@media (max-width: 800px) {
    #gallery {
        display: flex;
        align-items: flex-start;
        flex-wrap: wrap;
        justify-content: center;
    }
    #gallery > div {
        width: 48%;
        margin: 1%;
    }
}
@media (max-width: 800px) and (max-width: 350px) {
    #gallery > div {
        width: 98%;
    }
}
#gallery > div:nth-child(6n + 1) {
    grid-column: span 2;
    grid-row: span 2;
}
#gallery > div:nth-child(2) {
    grid-column: span 3;
    grid-row: span 3;
}
#gallery > div:nth-child(4) {
    grid-column: span 1;
    grid-row: span 2;
}
#gallery > div > a {
    opacity: 0;
    position: absolute;
    color: #000;
    background-color: #000;
    font: bold 4em "Helvetica";
    text-shadow: 0 -1px 5px #fff, -1px 0px 5px #fff, 0 1px 5px #fff, 1px 0px 5px #fff;
    padding: 2rem;
    mix-blend-mode: difference;
    width: 100%;
    height: 100%;
    transition: all ease 1s;
}
#gallery > div > img {
    width: 100%;
    min-height: 100%;
    transition: all ease 1s;
    object-fit: cover; /* !!! */
}
#gallery > div:hover img {
    filter: blur(4px);
}
#gallery > div:hover a {
    opacity: 1;
}
#gallery > div {
    overflow: hidden;
    position: relative;
    box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2), 0 3px 20px 0 rgba(0, 0, 0, 0.19);
}
#gallery div, #gallery a {
    display: flex;
    justify-content: center;
    align-items: center;
    text-decoration: none;
}
[id^ = "lightbox-"] {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    opacity: 0;
    transition: opacity 450ms ease-in-out;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
[id^ = "lightbox-"]:target {
    opacity: 1;
    pointer-events: inherit;
}
[id^ = "lightbox-"]:target img {
    filter: blur(0);
}
[id^ = "lightbox-"] .content {
    max-width: 90%;
    position: relative;
    color: #fff;
}
[id^ = "lightbox-"] .content:hover > a.close {
    opacity: 1;
    transform: scale(1, 1);
}
[id^ = "lightbox-"] .content:hover > .title {
    opacity: 1;
    transform: translateY(-3px);
}
[id^ = "lightbox-"] .content:hover > .title::after {
    opacity: 1;
}
[id^ = "lightbox-"] .content > * {
    transition: all 450ms ease-in-out;
}
[id^ = "lightbox-"] .title {
    display: block;
    margin: 0;
    padding: 1em;
    position: absolute;
    bottom: 0;
    width: 100%;
    transform: translateY(50%);
    font-size: 1.5em;
    opacity: 0;
}
[id^ = "lightbox-"] .title::after {
    content: ' ';
    background-color: rgba(0, 0, 0, 0.4);
    bottom: 0;
    left: 0;
    height: 100%;
    width: 100%;
    position: absolute;
    transition: all 350ms ease-in-out 250ms;
    opacity: 0;
    transform-origin: bottom;
    mix-blend-mode: soft-light;
}
[id^ = "lightbox-"] img {
    max-height: 90vh;
    max-width: 100%;
    margin: 0;
    padding: 0;
    filter: blur(50px);
}
[id^ = "lightbox-"] a.close {
    width: 2em;
    height: 2em;
    position: absolute;
    right: 0;
    top: 0;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    transform: scale(0, 0);
    opacity: 0;
    transform-origin: right top;
    text-decoration: none;
    color: #fff;
}
[id^ = "lightbox-"] a.close::after {
    content: "×";
}

Спасибо, с вашим кодом мне удалось показать изображения из БД. Это был мой первый раз, когда я читал loop.index. Я пытался передать список и использовать вложенный цикл for, но он не выходил.

user15316630 19.01.2023 15:05

Однако у меня есть другая проблема, пожалуйста, помогите, если у вас есть время, функция всплывающего окна работает только для первого изображения. Я пытался проверить обработку CSS, но безрезультатно <a href = "#lightbox-[index1]">image_text</a> заставляет изображение всплывать, другие изображения не реагируют на это

user15316630 19.01.2023 16:21

К сожалению, я не могу сказать, почему это не работает должным образом для вас. Я проверил это, и это работает для меня. Пока атрибут href указывает на идентичный атрибут id другого элемента, якорь на странице работает. Остальное регулируется правилами таблицы стилей, которые начинаются с [id^ = "lightbox-"] и должны одинаково применяться ко всем наложениям.

Detlef 19.01.2023 17:33

Я также пытаюсь прочитать [id^ = "lightbox-"] его новый синтаксис, но я думаю, что все еще не могу его реализовать. Я собираюсь сделать еще одну попытку. Не могли бы вы также поделиться своим кодом на github, пожалуйста

user15316630 20.01.2023 08:52

Я добавил весь пример кода в ответ. Это должно сработать. Правило [id^ = "lightbox-"] применяется ко всем элементам, атрибут id которых начинается с «lightbox-».

Detlef 20.01.2023 18:06

Гений! Функциональность безупречна. Спасибо, что поделились, вы действительно получили все тонкости технологии. Учитывая, что я буду много работать с веб-сайтами и Python, какие ресурсы вы могли бы мне предложить, чтобы получить некоторый уровень оценки связи js, css и python.

user15316630 21.01.2023 06:06

Для Flask я бы порекомендовал вам прочитать туториал Мигеля Гринберга . Для HTML, CSS и JS я бы порекомендовал взглянуть на документацию Mozilla Developer Network . В разделе CSS Tricks вы найдете отдельные статьи по макетам и конкретным проблемам. Не знаю, поможет ли это вам, но мне сложно дать рекомендацию по этим темам.

Detlef 21.01.2023 13:43

Другие вопросы по теме