Я пока думаю над этим, нашел эту фичу именно читая этот топик. Раньше я всегда отдельно писал АПИ для возврата JSON, отдельно для браузера
У меня будут еще мобильные приложения и наличие такого ответа сильно упрощает код
А что значит создавать? Вот у нас есть сотрудница, с опытом в биотехе. Под нее специально создавали позицию и специальные условия, чтобы она не увольнялась, когда было закрыт филиал в РФ. Для ценных сотрудников - спецальные условия. И это именно за их знания.
Гении-самоучки, конечно существуют. Но в целом хорошая база - большое подспорье. Даже изучение нейросетей требует хорошей математики. Мне вот часто ее не хватает и приходится отматывать работу к изучению/вспоминанию основ. А как продавать свои знания - отдельный вопрос.
Для пользователя (тот что на уровне шаблона уже) это будет выглядеть так
Конечный синтаксис еще не утвержден, но примерно как то так
<!DOCTYPE html><html lang="ru"> <head> {% include "head.html" %} </head> <body> {% include "navbar-main.html" %} <main class="container-fluid py-4"> {% block content %}{% endblock %} </main> {% include "footer.html" %} {% include "cookie-consent.html" %} <script> (function () { const csrfToken = "{{ csrf_token | default('') }}"; if (!csrfToken) return; const forms = document.querySelectorAll("form"); forms.forEach((form) => { if (form.querySelector('input[name="csrf_token"]')) return; const input = document.createElement("input"); input.type = "hidden"; input.name = "csrf_token"; input.value = csrfToken; form.appendChild(input); }); })(); </script> <script src="/static/js/cookie-consent.js"></script> </body></html>
А потом просто наследуешься от него и создаешь кастомные страницы, переопределяя нужные тебе блоки таким образом -
{% extends "base.html" %}{% block content %}<link rel="stylesheet" href="{{ url_for('static', path='/css/errors.css') }}"><div class="container"> <div class="row justify-content-center align-items-center" style="min-height: 70vh;"> <div class="col-md-8 text-center"> <div class="error-content"> <h1 class="display-1 fw-bold text-danger">403</h1> <h2 class="mb-4">Access Forbidden</h2> <p class="lead text-muted mb-4"> {{ error_message or "You don't have permission to access this resource." }} </p> <div class="mb-4"> <i class="bi bi-shield-exclamation text-danger" style="font-size: 5rem;"></i> </div> <div class="alert alert-warning mx-auto" style="max-width: 600px;"> <i class="bi bi-info-circle"></i> <strong>Need access?</strong> Please contact the administrator or try logging in with appropriate credentials. </div> <div class="d-flex justify-content-center gap-3 mt-4"> <a href="{{ url_for('index', lang=language) }}" class="btn btn-primary btn-lg"> <i class="bi bi-house-door"></i> Go to Home </a> {% if not is_authenticated %} <a href="{{ url_for('user_login', lang=language) }}" class="btn btn-success btn-lg"> <i class="bi bi-box-arrow-in-right"></i> Login </a> {% endif %} <button onclick="window.history.back()" class="btn btn-outline-secondary btn-lg"> <i class="bi bi-arrow-left"></i> Go Back </button> </div> </div> </div> </div></div>{% endblock %}
Отличная получилсь дискуссия, пока меня упекли(за дело) в баню. Зарекаюсь с экономистами дальше дискутировать)))Александр, Алексей, MrPi(Сорри, не знаю настоящего имени) - спасибо! Впервые за долгое время - конструктивный разговор, Даже вставки флудеров не испортили.Дискуссия кстати заставила копнуть разницу между Симфони и Фастапи. Стал понимать ваши трудности. Мне кажется в ФА более логичная структура и правильный рендер аутпута. Если в симфони профайлер рендерит через тэги, то Фастапи использует шаблоны и готовый контекст.Это гораздо быстрее.Ну и роутинг удобнее. Причем можно создавать роуты, которые одновременно будут уметь работать как с REST API, так и с HTML шаблонами.В чистом виде DRY
@router.get("/my-quizzes", name="my_quiz_list")async def my_quiz_list( request: Request, session: AsyncSession = Depends(get_async_session), current_user: dict = Depends(get_current_user_db), context: dict = Depends(page_context)): # 1. Получаем «универсальные» данные data = await get_my_quizzes_data(session, current_user.get('user_id')) # 2. Проверяем, что хочет клиент (Content Negotiation) accept_header = request.headers.get("accept", "") if "application/json" in accept_header: # Отдаем чистый JSON для API return data # 3. Если это браузер, подмешиваем данные в контекст Jinja2 full_context = {**context, **data} full_context["current_user"] = current_user full_context["page_title"] = "My Quizzes" return templates.TemplateResponse("my_quizzes.html", {"request": request, **full_context})
Все твои знания о Европе только с гуглокарт, это очевидно уже. Я то как раз и в курсе, для меня нормально на выходных сгонять куда за 1000 км. И видел я и пробки на платных автобанах и горные дороги, не говоря уже об обычных маршрутах по Польше. Придумал какую-то "стандартную" скорость и не умолкаешь. И нучись уже читать, понятно что когда дорога загружена, никто не будет моргать тебе. А если ты вылез в левую и тошнишь там - то запросто. Да, это не Беларусь, где тебя обгонят и начнут "учить", оттормаживаясь. Но на хвосте повиснуть могут запросто.
Я уже почти уверен что ты ни разу европейских дорог не видел.
То есть ты считаешь что это лучше?