Tianyu Liufang–Using Python+Vue3 to build a blog (1)

Tianyu Liufang – Use Python + Vue3 to build a blog (1)

Introduction:

I have been practicing for a year and a half on the front end and want to learn the back end. I feel that the gtp now has really greatly reduced the cost of learning a new language. gtp is like a Teachers who can answer basically all your questions 24 hours a day, take advantage of this to learn quickly and record the 天雨流香

tip: "The sky rains and the fragrance flows" is the Naxi phonetic translation. It is written on an archway next to Mufu in Lijiang. The Naxi phonetic meaning is "Go and study"

Set a small goal:

1. vue + fastapi management platform vue3 + ts The code must be neat and comfortable to look at.

2. A handsome blog page. I plan to write it in js. If I want SEO, I don’t know what else to do. If you guys see it, you can give me some advice.

3. If you have any questions or any place where you can write better and more refined code, I hope you guys can give me some pointers. I will focus on one, listen to advice, and seek knowledge! ! ! ! !

1. Project structure

├── blog/
│ ├── api/ # Interface routing definition
│ │ ├── __init__.py
│ │ ├── user_api.py
│ │ └── ...
│ │
│ ├── core/ # core code module
│ │ ├── __init__.py
│ │ ├── db.py
│ │ └── ...
│ │
│ ├── models/ # Data model
│ │ ├── __init__.py
│ │ ├── user_models.py
│ │ └── ...
│ │
│ ├── service/ # Function implementation
│ │ ├── __init__.py
│ │ └── ...
│ │
│ ├── tools/ # Other tools
│ │ ├── __init__.py
│ │ └── ...
│ │
│ ├── main.py
│ ├── requirements.txt
│ └── ...

2. Build mysql connection

# Path /core/db.py
import mysql.connector.pooling


class Database:
    _pool = None

    # Connection pool configuration parameters
    _pool_config = {<!-- -->
        "pool_name": "my_pool",
        "pool_size": 5,
        "pool_reset_session": True,
        "host": "localhost",
        "user": "******",
        "password": "******",
        "database": "******"
    }

    def __init__(self):
        if not Database._pool:
            Database._pool = mysql.connector.pooling.MySQLConnectionPool(**Database._pool_config)

    def insert_data(self, query, values):
        with self._get_connection() as connection:
            cursor = connection.cursor()
            cursor.execute(query, values)
            connection.commit()

    def find_data(self, query):
        with self._get_connection() as connection:
            cursor = connection.cursor()
            cursor.execute(query)
            result = cursor.fetchall()
        return result

    def _get_connection(self):
        return Database._pool.get_connection()

    def _release_connection(self, connection):
        connection.close()

    def __enter__(self):
        self._connection = self._get_connection()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self._release_connection(self._connection)

Encapsulate a mysql tool class. First, simply encapsulate two methods for inserting and querying. The specific use is shown in the adding routing module

3. Add routing module

# Path /api/user_api.py
from fastapi import APIRouter, HTTPException
from models.user_model import CreateUser
from service.user_server import User

router = APIRouter(
    prefix="/user",
    tags=["user"],
)
user = User()


@router.get("/")
def get_user():
    result = user.get_users()
    if result:
        return result
    else:
        raise HTTPException(status_code=404, detail="No users found")


@router.post('/add')
def add_user(request: CreateUser):
    result = user.create_user(request)
    return result

To use the routing module in fastapi, you need to define the path of each route in main.py. However, when there are many modules, if they are all written in main.py will be very bloated and difficult to maintain, so it is necessary for me to introduce APIRouter to handle multi-program classification, just like the blueprint in flask. After registering the number sub-module, you need to import the registration into the main.py file

# path /main.py
from fastapi import FastAPI
from api import user_api

app = FastAPI()

app.include_router(user_api.router)
# Then you can visit http://localhost:port number/user to query all data under the users table

4. Insert data & amp; & amp;parameter verification

1), api entry function

# Path /api/user_api.py
@router.post('/add')
def add_user(request: CreateUser = Body(...)):
    try:
        request = user.create_user(request)
        return create_response(code=200, msg='success', data=request)
    except HTTPException as e:
        error_detail = e.detail
        return {<!-- -->"error_message": error_detail}
    

2) Parameter verification model

# Path /models/user_model.py
from pydantic import BaseModel, Field
from typing import Optional

class CreateUser(BaseModel):
    username: str = Field(..., min_length=1, max_length=50, description='username', example="yu lon")
    password: str = Field(..., min_length=1, max_length=255, description='password', example='123456')
    email: Optional[str] = Field(None, min_length=1, max_length=100, description='Email', example='[email protected]')

3), specific database operations

# Path /service/user_server.py
from core.db import Database
from tools.time import get_current_time
from tools.uuid import use_uuid


class User:
    def __init__(self):
        self.db = Database()

    def get_users(self):
        query = "SELECT * FROM users"
        result = self.db.find_data(query)
        if result:
            return {<!-- -->"user": result}

    def create_user(self, data):
        _uuid = use_uuid()
        _username = data.username
        _password = data.password
        _email = data.email
        _create_time = get_current_time()
        query = "INSERT INTO users (user_id, username, password, email, created_at) VALUES (%s, %s, %s, %s, %s)"
        values = (_uuid, _username, _password, _email, _create_time)
        self.db.insert_data(query, values)
        return {<!-- -->"user_id": _uuid, "username": _username}

end:Some things learned along the way

1), positional parameters and keyword parameters

When I was looking at the encapsulated data return format, I saw a code written like this, and I wondered what the single * sign in the parameters meant. I went to study it briefly, as follows:

def greet(*,name, message):
    print(f"Hello, {<!-- -->name}! {<!-- -->message}")

greet("Alice", "How are you?") # error TypeError: create_response() takes 0 positional arguments but 2 were given. The error indicates two unexpected parameters.
greet(name="Alice",message="How are you?")# true Just replace it with keyword parameters

Positional Arguments:

Positional parameters are the way parameters are passed in the order they appear in the function definition. This means that the first parameter value will be assigned to the first parameter of the function definition, the second parameter value will be assigned to the second parameter of the function definition, and so on. Example:

def greet(name, message):
    print(f"Hello, {<!-- -->name}! {<!-- -->message}")

greet("Alice", "How are you?")

In the above example, “Alice” is passed to the name parameter and “How are you?” is passed to the message parameter, which is the usage of positional parameters.

Keyword Arguments:

def greet(name, message):
    print(f"Hello, {<!-- -->name}! {<!-- -->message}")

greet(message="How are you?", name="Bob")

In the above example, parameter names are used to explicitly specify which parameter should get which value, which is the usage of keyword parameters.

**Summary:** Keyword arguments are often more readable, especially when a function has multiple parameters or the order of the parameters is easily confused. They also provide greater flexibility, as you can pass parameters in a different order and certain parameters can be omitted. The order of positional parameters in the function definition is fixed, so the parameters must be passed in this order.

Next step:

1. Perfecting the package of response

2. Add token authentication, encryption, etc.

3. Let’s see what’s missing. The framework is ready.