Jednoduchý blog vo Flasku

Marek Mansell

SPy o.z.

Jednoduchý blog

vo Flasku

  1. Úvod do Flasku
    (templating, urls, bootstrap)
     
  2. Jednoduché pridávanie blog postov
    (SQLAlchemy, SQLite, forms)
     
  3. Autentifikácia a užívatelia
    (flask-login, užívateľské profily)

Kto používa Flask?

web

GET www.pycon.sk

Minimálna Flask aplikácia

from flask import Flask
app = Flask(__name__)

@app.route("/")
def home():
    return "Ahoj, svet!"

blog / blog.py :

Vytvorte adresár blog so súborom blog.py

blog/
└── blog.py

Spustenie Flask aplikácie

Unix Bash (Linux & MacOS):

$ export FLASK_APP=blog.py
$ export FLASK_ENV=development
$ flask run
> set FLASK_APP=blog.py
> set FLASK_ENV=development
> flask run
> $env:FLASK_APP = "blog.py"
> $env:FLASK_ENV = "development"
> flask run

Windows PowerShell:

Windows CMD (príkazový riadok):

Spustite v adresári blog !

V prehliadači: 127.0.0.1:5000

web

GET www.pycon.sk

@app.route("/")
return "Ahoj, svet!"

Posielame HTML

from flask import Flask
app = Flask(__name__)

@app.route("/")
def home():
    return "<h1>Super Blog</h1>"

blog / blog.py :

Prvá podstránka

from flask import Flask
app = Flask(__name__)

@app.route("/")
def home():
    return "<h1>Super Blog</h1>"

@app.route("/kontakt/")
def contact():
    return "Tu sa vypíše kontakt"

blog / blog.py :

Templates (šablóny)

blog
├── blog.py
└── templates
    └── home.html

Vytvoríme adresár templates so súborom home.html

<!doctype html>
<html lang="sk">
  <head>
    <title>Názov stránky</title>
  </head>
  <body>
    <h1>Super Blog</h1>
    <p>Obsah stránky</p>
  </body>
</html>

blog / templates / home.html :

Templates (šablóny)

blog / blog.py :

from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
def home():
    return render_template('home.html')

@app.route("/kontakt/")
def contact():
    return "Tu sa vypíše kontakt"

Vytvorte html šablónu pre /kontakt

<!doctype html>
<html lang="sk">
  <head>
    <title>Názov stránky</title>
  </head>
  <body>
    <h1>Kontakt na mňa</h1>
    <p>Meno: Marek Mansell</p>
    <p>Mail: marek.mansell@pycon.sk</p>
    <p>Telefón: 0904 000 111</p>
  </body>
</html>

blog / templates / contact.html :

Príklad HTML šablóny pre /kontakt

@app.route("/kontakt/")
def contact():
    return render_template('contact.html')

blog / blog.py :

Links (odkazy)

blog / templates / home.html :

  <body>
    <a href="https://pycon.sk">PyCon SK</a>
    <h1>Super Blog</h1>
    <p>Obsah stránky</p>
  </body>
<a href="https://pycon.sk">PyCon SK</a>

Odkazy v rámci Flasku

blog / templates / home.html :

  <body>
    <a href="https://pycon.sk">PyCon SK</a>
    <a href="{{ url_for('contact') }}">Zobraziť kontakt</a>
    <h1>Super Blog</h1>
    <p>Obsah stránky</p>
  </body>
<a href="https://pycon.sk">PyCon SK</a>
<a href="{{ url_for('contact') }}">Zobraziť kontakt</a>
@app.route("/kontakt/")
def contact():
    return render_template('contact.html')

blog / blog.py :

  • Vytvorte odkaz na úvodnú stránku "home"

  • Tieto 3 odkazy vložte aj na /kontakty

<body>
    <a href="https://pycon.sk">PyCon SK</a>
    <a href="{{ url_for('contact') }}">Zobraziť kontakt</a>
    <a href="{{ url_for('home') }}">Úvodná stránka</a>
    <h1>Kontakt na mňa</h1>
    <p>Meno: Marek Mansell</p>

blog / templates / contact.html :

<body>
    <a href="https://pycon.sk">PyCon SK</a>
    <a href="{{ url_for('contact') }}">Zobraziť kontakt</a>
    <a href="{{ url_for('home') }}">Úvodná stránka</a>
    <h1>Super Blog</h1>
    <p>Obsah stránky</p>

blog / templates / home.html :

Jednoduché "menu"

<!doctype html>
<html lang="sk">
  <head>
    <title>Názov stránky</title>
  </head>
  <body>
    <a href="https://pycon.sk">PyCon SK</a>
    <a href="{{ url_for('contact') }}">
      Zobraziť kontakt</a>
    <a href="{{ url_for('home') }}">
      Úvodná stránka</a>
    <h1>Super Blog</h1>
    <p>Obsah stránky</p>
  </body>
</html>

blog / templates / contact.html :

<!doctype html>
<html lang="sk">
  <head>
    <title>Názov stránky</title>
  </head>
  <body>
    <a href="https://pycon.sk">PyCon SK</a>
    <a href="{{ url_for('contact') }}">
      Zobraziť kontakt</a>
    <a href="{{ url_for('home') }}">
      Úvodná stránka</a>
    <h1>Kontakt na mňa</h1>
    <p>Meno: Marek Mansell</p>
    <p>Mail: marek.mansell@pycon.sk</p>
    <p>Telefón: 0904 000 111</p>
  </body>
</html>

blog / templates / home.html :

Veľa duplicitného kódu

Dedenie v šablónach

<!doctype html>
<html lang="sk">
  <head>
    <title>Názov stránky</title>
  </head>
  <body>
    <a href="https://pycon.sk">PyCon SK</a>
    <a href="{{ url_for('contact') }}">Zobraziť kontakt</a>
    <a href="{{ url_for('home') }}">Úvod</a>
    {% block content %}{% endblock %}
  </body>
</html>

blog / templates / base.html :

{% extends "base.html" %}

{% block content %}
  <h1>Super Blog</h1>
  <p>Obsah stránky</p>
{% endblock %}

blog / templates / home.html :

Upravte contact.html tak, aby tiež dedila z base.html

blog / templates / contact.html :

Dedenie v contact.html

{% extends "base.html" %}

{% block content %}
  <h1>Kontakt na mňa</h1>
  <p>Meno: Marek Mansell</p>
  <p>Mail: marek.mansell@pycon.sk</p>
  <p>Telefón: 0904 000 111</p>
{% endblock %}

blog / templates / base.html :

Štýlovanie s CSS

<!doctype html>
<html lang="sk">
  <head>
    <title>Názov stránky</title>
  </head>
  <body>
    <div style="background-color: yellow; margin-bottom: 100px;">
      <a href="https://pycon.sk">PyCon SK</a>
      <a href="{{ url_for('contact') }}">Zobraziť kontakt</a>
      <a href="{{ url_for('home') }}">Úvod</a>
    </div>
    {% block content %}{% endblock %}
  </body>
</html>

Štýlovanie s CSS

blog
├── blog.py
├── static
│   └── style.css
└── templates
    └── index.html

Vytvoríme adresár static so súborom style.css

blog / static / style.css :

.my-menu {
  background-color: lightblue;
  margin-bottom: 100px;
}

blog / templates / base.html :

Štýlovanie s CSS

<!doctype html>
<html lang="sk">
  <head>
    <title>Názov stránky</title>
    <link rel="stylesheet" type="text/css"
          href="{{ url_for('static', filename='style.css') }}">
  </head>
  <body>
    <div class="my-menu">
      <a href="https://pycon.sk">PyCon SK</a>
      <a href="{{ url_for('contact') }}">Zobraziť kontakt</a>
      <a href="{{ url_for('home') }}">Úvod</a>
    </div>
    {% block content %}{% endblock %}
  </body>
</html>
<link rel="stylesheet" type="text/css"
      href="{{ url_for('static', filename='style.css') }}">

Bootstrap

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>

blog / templates / base.html :

<!doctype html>
<html lang="sk">
  <head>
    <title>Názov stránky</title>
    <link rel="stylesheet" type="text/css"
          href="{{ url_for('static', filename='style.css') }}">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
  </head>
  <body>
    <div class="my-menu">
      <a href="https://pycon.sk">PyCon SK</a>
      <a href="{{ url_for('contact') }}">Zobraziť kontakt</a>
      <a href="{{ url_for('home') }}">Úvod</a>
    </div>

    {% block content %}{% endblock %}

    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
  </body>
</html>

Bootstrap

Documentation > Components > Navbar > Nav

blog / templates / base.html :

<body>

  <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
      <div class="navbar-nav">
        <a class="nav-item nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
        <a class="nav-item nav-link" href="#">Features</a>
        <a class="nav-item nav-link" href="#">Pricing</a>
        <a class="nav-item nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
      </div>
    </div>
  </nav>

  <div class="my-menu">
    <a href="https://pycon.sk">PyCon SK</a>
    <a href="{{ url_for('contact') }}">Zobraziť kontakt</a>
    <a href="{{ url_for('home') }}">Úvod</a>
  </div>

Bootstrap

blog / templates / base.html :

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="{{ url_for('home') }}">SPy o.z.</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse"
          data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup"
          aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
      <a class="nav-item nav-link active" href="{{ url_for('home') }}">Úvod</a>
      <a class="nav-item nav-link" href="{{ url_for('contact') }}">Kontakt</a>
      <a class="nav-item nav-link" href="https://pycon.sk">PyCon SK</a>
    </div>
  </div>
</nav>

Bootstrap

Responzivita

Farba Navbaru

blog / templates / base.html :

<nav class="navbar navbar-expand-lg navbar-dark bg-dark">

blog / templates / base.html :

<div class="container">
  {% block content %}{% endblock %}
</div>

Containers

blog / blog.py :

from random import choice

Náhodné Vtipy

blog / templates / joke.html :

{% extends "base.html" %}

{% block content %}
  <h1>Ahoj! Tu maš ÍTčkarsky vtip:</h1>
  <p>{{ joke }}</p>
{% endblock %}
@app.route("/vtip/")
def joke():
    return render_template('joke.html', joke=choice(jokes))
jokes = [
    "3 Database Admins walked into a NoSQL bar. A little later, they walked out because they couldn’t find a table.",
    "The C language combines all the power of assembly language with all the ease-of-use of assembly language.",
    "8 bytes walk into a bar, the bartenders asks \"What will it be?\" One of them says, \"Make us a double.\"",
    "Chuck Norris doesn’t have disk latency because the hard drive knows to hurry the hell up.",
]
@app.route("/vtip/")
def joke():
    return choice(jokes)

Čítanie z url

blog / blog.py :

@app.route("/vtip/")
@app.route("/vtip/<name>/")
def joke(name="Tajomný Neznámy"):
    return render_template('joke.html', joke=choice(jokes), name=name)

blog / templates / joke.html :

{% extends "base.html" %}

{% block content %}
  <h1>Ahoj {{ name }}! Tu maš ÍTčkarsky vtip:</h1>
  <p>{{ joke }}</p>
{% endblock %}

Python Anywhere

blog
├── blog.py
├── static
│   └── style.css
└── templates
    └── base.html
    └── contact.html
    └── index.html

Vytvoríme adresár img a pridáme fotku marek.jpg

Súbory

Adresáre

Menu 'active'

blog / blog.py :

return render_template('joke.html', joke=choice(jokes),
                       name=name, active_page='joke')

blog / templates / base.html :

<a class="nav-item nav-link
   {{ 'active' if active_page == 'joke' else '' }}"
   href="{{ url_for('joke') }}">Vtip</a>
<a class="nav-item nav-link active"
   href="{{ url_for('joke') }}">Vtip</a>

Pridajte do base.html medzeru (angl. space) nad "content" stránky

blog / templates / base.html :

<div class="container mt-5">
  {% block content %}{% endblock %}
</div>

Spacing

Inspect Element

Images

blog / templates / contact.html :

{% block content %}
  <img src="{{ url_for('static', filename='img/marek.jpg') }}"
       class="img-fluid" alt="Image of Marek">

Obrázok zatiaľ neexistuje

blog
├── blog.py
├── static
│   ├── img
│   │   └── marek.jpg
│   └── style.css
└── templates
    └── index.html

Vytvoríme adresár img a pridáme fotku marek.jpg

Made with Slides.com