0

Dev IOS tìm hiểu Flask (Part 2)

Chào các bạn. nếu các bạn chưa đọc part 1 có thể vào đây để xem nha.

Tiếp tục phần trước mình sẽ giải thích trong code các phần còn lại và chạy thử ở postman nhé các bạn.

Resources

User

from flask_restful import Resource, reqparse
from models.user import UserModel

Resource sẽ là class cha của UserRegisterUserModel chúng ta import để kết nối tới database

Nếu chúng ta tạo một user thì username và passworrd không nên đặt ở trên url, do đó chúng ta sẽ gửi cùng với bên trong body của request, khi đó reqparse sẽ giúp chúng ta việc này

parser = reqparse.RequestParser()
    parser.add_argument('username',
        type=str,
        required=True,
        help="This field cannot be left blank."
    )
    parser.add_argument('password',
        type=str,
        required=True,
        help="This field cannot be left blank."
    )

Chúng ta định nghĩa những tham số quan trọng và set thông báo nếu tham số đó thiếu hoặc sai. Nếu có thêm nhiều tham số trong body, parser sẽ không để ý chúng.

Những phương thức HTTP mà chúng ta hay gặp là GET, POST, DELETE, PUT,... Chúng ta chỉ cần tạo User do đó API của chúng ta chỉ cần một function là POST

def post(self):
    data = UserRegister.parser.parse_args()

Chúng ta lấy data từ parser, bây giờ chúng ta có username và password bởi vì đó là 2 tham số của chúng ta

if UserModel.find_by_username(data['username']):
    return {"message": "User already exists"}, 400

Chúng ta kiểm tra nếu trong database đã có username này thì chúng trả về một json có message với status code là 400, có nghĩa là "Bad Request"

user = UserModel(**data)
user.save_to_db()

return {"message": "User created successfully."}, 201

Còn nếu không có thì chúng ta sẽ tạo một UserModel từ data, sau đó lưu vào database, trả về một json có message với status code là 201, có nghĩa là "Created"

School

Chúng ta định nghĩa những phương thức HTTP như sau

  • GET một school bằng tên
  • POST một school với tên
  • DELETE một school bằng tên
  • GET tất cả schools

Chúng ta sẽ chia Resource này thành 2 Resoucces là SchoolSchoolList bởi vì chúng ta có 2 phương thức GET, một cái sẽ được đươc gọi trong /school và cái còn lại ở /schools.

class School(Resource):
    def get(self, name):
        school = SchoolModel.find_by_name(name)
        if school:
            return school.json()
        return {'message': 'School not found'}, 404

    def post(self, name):
        if SchoolModel.find_by_name(name):
            return {'message': "School '{}' already exists".format(name)}, 400

        school = SchoolModel(name)
        try:
            school.save_to_db()
        except:
            return {'message': 'An error occurred while creating the school'}, 500

        return school.json(), 201

    def delete(self, name):
        school = SchoolModel.find_by_name(name)
        if school:
            school.delete_from_db()

        return {'message': 'School deleted'}

class SchoolList(Resource):
    def get(self):
        return {'schools': list(map(lambda x: x.json(), SchoolModel.query.all()))}

Những phương thức GET, POST, DELETE trong School và GET trong SchoolList rất dễ hiểu, giống với UserRegister nên mình sẽ không nói ở đây.

Student

Có một sự khác biệt nhỏ ở đây là chúng ta import thêm một thư viện

from flask_jwt import jwt_required

Cái này dành cho những resquest mà chúng ta sử dụng JWT Authentication

Nói qua về phương thức POST chúng ta đã tạo

@jwt_required()
def post(self, name):
    if StudentModel.find_by_name(name):
        return {'message': "A student with name '{}' already exists.".format(name)}, 400

        data = Student.parser.parse_args()

        student = StudentModel(name, **data) # (name, data['name'], data['school_id'])

        try:
            student.save_to_db()
        except:
            return {'message': 'An error ocurred inserting the student.'}, 500

        return student.json(), 201

Chúng ta có @jwt_required() để giúp Flask hiểu chúng ta cần JWT access_token để chạy phương thức này, nếu sai token thì phương thức sẽ trả về error Phần còn lại thì giống như tạo User

Security

Để xác thực người dùng, chúng ta có những phương thức như sau

def authenticate(username, password):
    user = UserModel.find_by_username(username)
    if user and user.password == password:
        return user

Nếu chúng ta tìm thấy User trong database và password trùng với password trong database thì chúng ta trả về user. User không thực sự trả về tới client bởi vì không có ích gì cả, client cần một access_token cho những request sau này, flask_jwt sẽ xử lý việc này và gửi tới client access_token

def identity(payload):
    user_id = payload['identity']
    return UserModel.find_by_id(user_id)

Phương thức thứ hai là identity, phương thức này được gọi khi một phương thức được đánh dấu với @jwt_required()

App.py

File này hiểu đơn giản là main app Phần import khá là dễ hiểu, chúng ta import những thư viện cần dùng và những resources

from flask import Flask
from flask_restful import Api
from flask_jwt import JWT

from security import authenticate, identity
from resources.user import UserRegister
from resources.student import Student, StudentList
from resources.school import School, SchoolList
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

Tại đây chúng ta khởi tạo một đối tượng Flask và config những yêu cầu cần thiết, thông tin về config các bạn có thể trong trang chủ của Flask ở đây Ở đây chúng ta dùng SQLite nhưng vẫn có thể dùng MySQL hoặc PostrgeSQL.

app.secret_key = 'dante'

Chúng ta định nghĩa khoá để access_token được mã hoá, nên là một khoá nào đó khó đoán

api = Api(app)
api.add_resource(School, '/school/<string:name>')
api.add_resource(Student, '/student/<string:name>')
api.add_resource(SchoolList, '/schools')
api.add_resource(StudentList, '/students')

api.add_resource(UserRegister, '/register')

Chúng ta tạo một đối tượng Api từ thư viện flask_restful và định tuyến đến những resource cho các phương thức GET, POST, DELETE chúng ta đã viết

jwt = JWT(app, authenticate, identity)

Đối tượng JWT được tạo có tham số là app, 2 phương thức chúng ta đã nói ở phần security

if __name__ == '__main__':
    from db import db
    db.init_app(app)
    app.run(port=5000, debug=True)

Câu lệnh if này để nếu chúng ta chạy file từ Terminal, python sẽ ấn định file __name__ đó thành __main__

Chạy Sever

Đầu tiên chúng ta mở Terminal lên, cd đến folder có file app.py và chạy các lệnh sau

virtualenv venv

Tạo môi trường chạy sever từ phần 1 mình đã nói

. venv/bin/activate 

Activate môi trường

pip install flask 
pip install flask-restful
pip install flask-jwt
pip install flask-sqlalchemy

Cài đặt những thư viện cần thiết

python3 app.py

Khi hoàn thành những việc trên thì terminal của bạn trông sẽ như thế này

Chúng ta sẽ test API ở trên bằng phần mềm Postman như sau.

Create User

Chúng ta test API tạo user phương thức POST bên Url và body như hình dưới, sau khi bấm Send thì kết quả trả về thành công.

Login

Tiếp theo chúng ta test API đăng nhập người dùng như sau. Kết quả trả về là một access_token

Lưu access_token này lại sau này chúng ta sẽ cần dùng đến nó.

School

Bây giờ chúng ta sẽ tạo một School tên Sun như sau:

Bạn có thể thử với DELETE, GET và GET tất cả schools nha.

Student

Bây giờ hãy tạo một student với tên ThanhDat như sau

Nếu không có access_token thì kết quả trả về sẽ lỗi ngay, sửa lại Url một chút chúng ta sẽ được như sau, thêm body có School_id là 1 nữa chúng ta sẽ tạo được Student


Vậy là mình đã hướng dẫn xong cơ bản về Flask để các bạn có thể tự viết một API đơn giản rồi, hi vong nó sẽ giúp ích công việc các bạn sau này 😄

Cảm ơn các bạn đã đọc bài đến đây.

Nguồn: https://hackernoon.com/learning-flask-being-an-ios-developer-3c6ec8c2ba83


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí