React, Flask-restful i SQLAlchemy – pobranie danych z bazy danych

Frontend:

Dane z backendu pobieram przy wybraniu z opcji menu komponentu Navbar frameworka Bulma. Aby dane były wczytane podczas randerowania komponentu używam hook useEffect. Tworzone jest wówczas zapytanie do backendu, a jako parametr przekazywany jest token, ustawiany podczas logowania użytkownika. Z backendu przesyłana jest odpowiedź w formie obiektu Promise, z którego jeśli zapytanie zostało zakończone sukcesem jest ustawiana zmienna cursor (zmiana stanu za pomocą setCursor). Cursor i funkcja setCursor przekazywane są do komponentu z komponentu nadrzędnego App.js jako parametry (props) tzn.

import LoginForm from '../Forms/LoginForm/LoginForm'
import { useEffect } from "react";

function Contracts({token, putToken, cursor, setCursor}) {

    useEffect( 
        () => {
            const token = sessionStorage.getItem('token')
            fetch('/api/contract/' + token)
            .then(res => res.json()).then(data => setCursor(data)).catch((err) => console.log(err))
        }, [token, setCursor],
    );
    
    if (!token) {
        return <LoginForm putToken={putToken} />
    };

Aby komponent odświeżał dane po poprawnym zalogowaniu się w dodatkowym parametrze metody useEffect w tablicy umieściłem zmienną token, która zostaje ustawiona w komponencie LoginForm.js

Aby komponent odświeżał dane po zmianie zawartości cursora np. poprzez dodanie nowego kontraktu jako dodatkowy parametr metody useEffect umieściłem funkcję setCursor.

Poszczególne wiersze danych są umieszczane w tabeli tzn.

<tbody>
    {cursor && Object.keys(cursor).map((keyName, keyIndex) => 
    <tr key={keyIndex}>
            <td>{keyIndex+1}</td>
            <td>{(cursor[keyName].status)}</td>
            <td>{(cursor[keyName].contract_number)}</td>
            <td>{(cursor[keyName].contractor)}</td>
            <td>{(cursor[keyName].customer)}</td>
            <td>{(cursor[keyName].date_of_order)}</td>
            <td>{(cursor[keyName].date_of_delivery)}</td>
            <td>{(cursor[keyName].pallets_position)}</td>
            <td>{(cursor[keyName].pallets_planned)}</td>
            <td>{(cursor[keyName].pallets_actual)}</td>
            <td>{(cursor[keyName].warehouse)}</td>
     </tr>)}   
</tbody>

Backend we Flask-restful:

W pliku __init__.py dodaję kolejną klasę zasobów:

from api.resources.contracts import AllContracts

api.add_resource(AllContracts, '/api/contract/<token>', endpoint='all_contracts')

W pliku contracts.py definiuję klasę zasobów:

from datetime import datetime
from flask import request
from flask_restful import Resource
from .. import db
from ..common.models import User, Contract

class AllContracts(Resource):
    def get(self, token):
        token = token.strip('"')
        user = User.query.filter_by(token=token).first()
        contracts = Contract.query.filter_by(customer=user.username).order_by(Contract.id.desc()).all()
        cursor = {}
        for i, contract in enumerate(contracts):
            cursor[i] = contract.serialize()
        return cursor

W pliku models.py definiuję m.in. jak klasa Contract dziedzicząca po klasie Model z SQLAlchemy ma być serializowana:

from .. import db
from datetime import datetime

class Contract(db.Model):
    '''Model of contract between a contractor and a customer'''

    id = db.Column(db.Integer, primary_key=True)
    status = db.Column(db.String(10), nullable=False, default='open')
    contract_number = db.Column(db.String(20), nullable=False)
    contractor = db.Column(db.String(20), db.ForeignKey('user.username'), nullable=False)
    customer = db.Column(db.String(20), db.ForeignKey('user.username'), nullable=False)
    date_of_order = db.Column(db.Date, nullable=False, default=datetime.utcnow)
    date_of_delivery = db.Column(db.Date, nullable=False)
    pallets_position = db.Column(db.Integer)
    pallets_planned = db.Column(db.Integer, nullable=False)
    pallets_actual = db.Column(db.Integer)    
    warehouse = db.Column(db.String(10), nullable=False)

    def serialize(self):
        return {'id': self.id,
                'status': self.status,
                'contract_number': self.contract_number,
                'contractor': self.contractor,
                'customer': self.customer,
                'date_of_order': datetime.strftime(self.date_of_order, '%Y-%m-%d'),
                'date_of_delivery': datetime.strftime(self.date_of_delivery, '%Y-%m-%d'),
                'pallets_position': self.pallets_position,
                'pallets_planned': self.pallets_planned,
                'pallets_actual': self.pallets_actual,
                'warehouse': self.warehouse 
                }

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

88 − = 79