Cтворюємо блог використовуючи Flask і AngularJS. Частина 1

11 хв. читання

У цьому уроці ми створимо блог за допомогою Flask і AngularJS.

Це перша частина курсу. В ній ми зосередимося на створенні REST API, який буде використовуватися додатком AngularJS.

Цілі

Цілі застосунку прості:

  • Реєстрація користувачів;
  • Їх авторизація;
  • Кожен авторизований користувач повинен мати можливість створити пост;
  • Відображення постів на домашній сторінці;
  • Функція "Вихід".

Вимоги

Це керівництво припускає, що ви добре знайомі з Python, налаштуванням віртуального середовища та роботою з терміналом.

Структура Каталогів

Структуру каталогів, що ми будемо використовувати повинна виглядати так:

Структура директорій

Встановлення необхідних пакунків Python

Ми використовуватимемо наступні пакети:

  • Flask-RESTful
  • Flask-SQLAlchemy
  • Flask-Bcrypt
  • Flask-HTTPAuth
  • Flask-WTF
  • WTForms-Alchemy
  • marshmallow

Щоб спростити задачу, створіть файл з ім'ям requirements.txt у blog/server/ каталог і додайте наступний текст:

Flask==0.10.1
Flask-Bcrypt==0.6.0
Flask-HTTPAuth==2.2.1
Flask-RESTful==0.2.12
Flask-SQLAlchemy==1.0
Flask-WTF==0.10.0
Jinja2==2.7.3
MarkupSafe==0.23
SQLAlchemy==0.9.7
SQLAlchemy-Utils==0.26.9
WTForms==2.0.1
WTForms-Alchemy==0.12.8
WTForms-Components==0.9.5
Werkzeug==0.9.6
aniso8601==0.83
decorator==3.4.0
infinity==1.3
intervals==0.3.1
itsdangerous==0.24
marshmallow==0.7.0
py-bcrypt==0.4
pytz==2014.4
six==1.7.3
validators==0.6.0
wsgiref==0.1.2

Перейдіть у директорію blog/server/ і виконайте команду pip install -r requirements.txt, щоб встановити необхідні пакети.

Початкові налаштування

Створіть новий файл у blog/server/app і назвіть його config.py, додайте до нього наступне:

DEBUG = True
WTF_CSRF_ENABLED = False

Потім, додайте файл server.py у blog/server/app. Скопіюйте і вставте в нього код:

import os
 
from flask import Flask
from flask.ext import restful
from flask.ext.restful import reqparse, Api
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.bcrypt import Bcrypt
from flask.ext.httpauth import HTTPBasicAuth
 
basedir = os.path.join(os.path.abspath(os.path.dirname(__file__)), '../')
 
app = Flask(__name__)
app.config.from_object('app.config')
 
# flask-sqlalchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'app.sqlite')
db = SQLAlchemy(app)
 
# flask-restful
api = restful.Api(app)
 
# flask-bcrypt
flask_bcrypt = Bcrypt(app)
 
# flask-httpauth
auth = HTTPBasicAuth()
 
@app.after_request
def after_request(response):
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
    response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
    return response
 
import views

В цьому файлі ми ініціалізуємо Flask, завантажуємо змінні налаштувань з конфігураційного файлу, створюємо flask-sqlalchemy, об'єкти flask-restful і т.д... Ми також додаємо деякі заголовки-відповіді у функцію after_request, яка дозволить CORS. Це надасть можливість розміщати сервер (REST API) і клієнт (AngularJS додаток) на різних доменах та піддоменах (приклад: api.example.com і example.com). Під час розробки, це дозволить запускати їх через різні порти (приклад: localhost:8000 і localhost:5000).

Моделі

Тепер, коли ми закінчили з початковими налаштуваннями, давайте визначимося з моделями. Створіть новий файл у blog/server/app каталог і назвіть його models.py, скопіюйте і вставте код:

from flask import g
 
from wtforms.validators import Email
 
from server import db, flask_bcrypt
 
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(120), unique=True, nullable=False, info={'validators': Email()})
    password = db.Column(db.String(80), nullable=False)
    posts = db.relationship('Post', backref='user', lazy='dynamic')
 
    def __init__(self, email, password):
        self.email = email
        self.password = flask_bcrypt.generate_password_hash(password)
 
    def __repr__(self):
        return '<user %r="">' % self.email
 
class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(120), nullable=False)
    body = db.Column(db.Text, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    created_at = db.Column(db.DateTime, default=db.func.now())
 
    def __init__(self, title, body):
        self.title = title
        self.body = body
        self.user_id = g.user.id
 
    def __repr__(self):
        return '<post %r="">' % self.title

У коді вище ми визначили User і Post моделі. User модель має id в якості первинного ключа, який визначається як ціле число, і поля email та password, які визначені як рядки. Вона також має зв'язок моделлю Post через поле posts. Модель Post також має id в якості первинного ключа, який також визначається як ціле число, і поля title та body, які визначені як рядки. Вона також має поле user_id, яке визначається як ціле число і як зовнішній ключ для поля id моделі User. Вона також має поле created_at, що визначається типом DateTime.

Форми

Тепер, коли ми закінчили визначення моделей, визначимо форми, які ми будемо використовувати для перевірки даних, що вводяться користувачем. Для перевірки форми, ми будемо використовувати розширення для Flask під назвою WTForms і доповнення WTForms-Alchemy - для більш швидкого та простого визначення нашої форми. Створіть новий файл під blog/server/app і назвіть його forms.py, а потім додайте наступний код:

from flask.ext.wtf import Form
 
from wtforms_alchemy import model_form_factory
from wtforms import StringField
from wtforms.validators import DataRequired
 
from app.server import db
from models import User, Post
 
BaseModelForm = model_form_factory(Form)
 
class ModelForm(BaseModelForm):
    @classmethod
    def get_session(self):
        return db.session
 
class UserCreateForm(ModelForm):
    class Meta:
        model = User
 
class SessionCreateForm(Form):
    email = StringField('email', validators=[DataRequired()])
    password = StringField('password', validators=[DataRequired()])
 
class PostCreateForm(ModelForm):
    class Meta:
        model = Post

Для того, щоб WTForms-Alchemy працювало з Flask-WTF, ми визначили клас з ім'ям ModelForm, який наслідується від BaseModelForm, наданий WTForms-Alchemy. Ви можете знайти більше інформації тут.

Якщо ви не розумієте, що відбувається у наведеному вище коді, я рекомендую вам ознайомитись з документацією WTForms і WTForms-Alchemy.

Серіалізатори

Щоб рендерити моделі даних у JSON форматі в наших відповідях, спочатку необхідно перетворити їх у нативні типи даних мови Python. Flask-RESTful може зробити це, використовуючи модуль полів і декоратор marshal_with() (докладніше - тут). Я не знав, що Flask-RESTful їх підтримує, коли почав будувати REST API, так що я використовував Marshmallow. Створіть новий файл у каталозі blog/server/app і назвіть його serializers.py, скопіюйте і вставте туди наступний код:

from marshmallow import Serializer, fields
 
class UserSerializer(Serializer):
    class Meta:
        fields = ("id", "email")
 
class PostSerializer(Serializer):
    user = fields.Nested(UserSerializer)
 
    class Meta:
        fields = ("id", "title", "body", "user", "created_at")

Views

Тепер, коли ми закінчили визначення потрібних нам моделей, форм і серіалізаторів, визначимося з view і їх використанням. Створіть новий файл у blog/server/app каталог і назвіть його views.py, скопіюйте і вставте код:

from flask import g
from flask.ext import restful
 
from server import api, db, flask_bcrypt, auth
from models import User, Post
from forms import UserCreateForm, SessionCreateForm, PostCreateForm
from serializers import UserSerializer, PostSerializer
 
@auth.verify_password
def verify_password(email, password):
    user = User.query.filter_by(email=email).first()
    if not user:
        return False
    g.user = user
    return flask_bcrypt.check_password_hash(user.password, password)
 
class UserView(restful.Resource):
    def post(self):
        form = UserCreateForm()
        if not form.validate_on_submit():
            return form.errors, 422
 
        user = User(form.email.data, form.password.data)
        db.session.add(user)
        db.session.commit()
        return UserSerializer(user).data
 
class SessionView(restful.Resource):
    def post(self):
        form = SessionCreateForm()
        if not form.validate_on_submit():
            return form.errors, 422
 
        user = User.query.filter_by(email=form.email.data).first()
        if user and flask_bcrypt.check_password_hash(user.password, form.password.data):
            return UserSerializer(user).data, 201
        return '', 401
 
class PostListView(restful.Resource):
    def get(self):
        posts = Post.query.all()
        return PostSerializer(posts, many=True).data
 
    @auth.login_required
    def post(self):
        form = PostCreateForm()
        if not form.validate_on_submit():
            return form.errors, 422
        post = Post(form.title.data, form.body.data)
        db.session.add(post)
        db.session.commit()
        return PostSerializer(post).data, 201
 
class PostView(restful.Resource):
    def get(self, id):
        posts = Post.query.filter_by(id=id).first()
        return PostSerializer(posts).data
 
api.add_resource(UserView, '/api/v1/users')
api.add_resource(SessionView, '/api/v1/sessions')
api.add_resource(PostListView, '/api/v1/posts')
api.add_resource(PostView, '/api/v1/posts/<int:id>')

Функція verify_password, яка декорована auth.verify_password, буде використовуватися Flask-HTTPAuth для автентифікації користувачів. Обирається користувач по електронній пошті і перевіряється, чи збігається пароль з паролем, що зберігаються в базі даних. UserView клас буде обробляти запити на реєстрацію користувача, SessionView клас буде обробляти запити на вхід, PostListView клас буде обробляти вибірки списків постів і запити на їх створення. І нарешті, PostView клас буде обробляти отримання окремого посту. У нижній частині файлу, ми просто налаштовуємо маршрутизацію ресурсу для API.

Створення бази даних

Ми також повинні створити файл з назвою db_create.py. Ми будемо запускати скрипт для ініціалізації бази даних. Тепер перейдіть у blog/server/і запустіть скрипт використовуючи python db_create.py

from app.server import db
 
db.create_all()

REST API сервер

Ще один файл, який ми повинні створити, це run.py. Через цей скрипт ми будемо запускати REST API сервер.

from app.server import app
 
app.run()

Якщо ви виконали описані вище дії правильно, ви повинні мати можливість запустити REST API сервер, зайшовши у каталог blog/server і запустивши python run.py

Останні кроки

Реєстрація користувача

Для реєстрації користувача необхідно відправити POST-запит на localhost:5000/API/В1/users. Обов'язкові поля: email і password. Ось приклад: curl --dump-header - -H "Content-Type: application/json" -X POST -d '{"email": "johndoe@gmail.com","password": "admin"}' http://localhost:5000/api/v1/users

Авторизація користувача

Для входу користувача в систему, вам необхідно відправити реквізити доступу користувача до localhost:5000/API/В1/сесій за допомогою запиту Post. Приклад: curl --dump-header - -H "Content-Type: application/json" -X POST -d '{"email": "johndoe@gmail.com","password": "admin"}' http://localhost:5000/api/v1/sessions

Створення посту

Щоб створити пост, вам потрібно відправити Post-запит на localhost:5000/API/В1/posts. Обов'язкові поля: title і body. Оскільки користувач зобов'язаний реєструватися при створенні посту, зверніть увагу, що вам також потрібно надіслати авторизаційний заголовок, що містить base64-закодовані облікові дані користувача, розділені двокрапкою (":"). Приклад: curl --dump-header - -H "Content-Type: application/json" -H "Authorization: Basic am9obmRvZUBnbWFpbC5jb206YWRtaW4=" -X POST -d '{"title": "Example post","body": "Lorem ipsum"}' http://localhost:5000/api/v1/posts

Отримання постів

Для вибірки всіх збережених постів, вам потрібно відправити запит GET на http://localhost:5000/api/v1/posts. Приклад: curl -i http://localhost:5000/api/v1/posts

Крім Curl, ви також можете використовувати Advanced REST Client - розширення для Chrome для перевірки API.

Що далі?

Перша частина уроку на цьому закінчується. У другій частині ми будемо фокусуватися на створенні angularjs веб-додатку, який буде використовувати API, який ми тільки що створили.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.9K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація