xxleyi / learning_list

聚集自己的学习笔记
11 stars 3 forks source link

Web Backend 问题清单 #156

Open xxleyi opened 5 years ago

xxleyi commented 5 years ago

Django: database-driven Web app

start

django-admin startproject mysite

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        wsgi.py

python manage.py runserver 0:5000

python manage.py startapp polls

polls/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

env setting

one settings.py and local_settings.py in different env timezone issue:

TIME_ZONE = "Asia/Shanghai"
USE_TZ = False

Data Model Layer within

standard ORM, query syntax and mature migration tool lazy QuerySet object, only execute when evaluated, such as len, slicing, bool, str, repr

dynamic admin interface: a whole house

# mysite/news/models.py
from django.db import models

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
# mysite/news/admin.py
from django.contrib import admin

from . import models

admin.site.register(models.Article)

That's it.

URL scheme

# mysite/news/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<int:pk>/', views.article_detail),
]

For example, if a user requested the URL “/articles/2005/05/39323/”, Django would call the function news.views.article_detail(request, year=2005, month=5, pk=39323).

That's it.

views

# mysite/news/views.py
from django.shortcuts import render

from .models import Article

def year_archive(request, year):
    a_list = Article.objects.filter(pub_date__year=year)
    context = {'year': year, 'article_list': a_list}
    return render(request, 'news/year_archive.html', context)

That's it.

templates

mysite/templates/base.html
{% load static %}
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <img src="{% static "images/sitelogo.png" %}" alt="Logo">
    {% block content %}{% endblock %}
</body>
</html>

Flask: keep the core simple but extensible, so be micro

env setting

one config.py and different cfg file in different env: local.cfg, test.cfg, real.cfg

Data Model Layer without

extension: flask-sqlalchemy, flask-migration

app = Flask(__name__)
db = SQLAlchemy()
db.init_app(app)
app.config["SQLALCHEMY_ENGINE_OPTIONS"] = dict(pool_size=30, pool_recycle=TIME_LESS_THAN_SQL_SERVER)

另外,对于 session 需要特殊关照,最好主动 commit and close

admin without

extension: flask-admin

URL scheme

app.route decorator and blueprint

views

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

That's it

templates

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}

context: current_app, g, request, session

Deferred Request Callbacks

from flask import request, after_this_request

@app.before_request
def detect_user_language():
    language = request.cookies.get('user_lang')

    if language is None:
        language = guess_language_from_request()

        # when the response exists, set a cookie with the language
        @after_this_request
        def remember_language(response):
            response.set_cookie('user_lang', language)
            return response

    g.language = language

That's it

before_request and after_request order

Reference from SO

Flask's after_request hooks are indeed executed in the reversed order of their declaration. Conversely, before_request hooks are executed in the order of their declaration.

If after_request hooks are declared on a blueprint, those are executed in reversed declaration order, before global after_request hooks. If before_request hooks are declared on a blueprint, those are executed in declaration order, after global before_request hooks.

See preprocess_request and process_response source code for implementation details.


Django vs Flask


Deploy: Nginx, Gunicorn, WSGI, Linux, Docker, K8s

xxleyi commented 5 years ago

how to enjoy Flask context in Django?

163