
Wenn Sie ein schnelles Admin-
Panel auf Ihrem Knie benötigen, in dem das Front-End "
React-Admin" und das Back-End "
Flask-RESTful" -API ist , müssen Sie diesen Code mindestens mehrere zehn Zeilen lang implementieren.
Backend Flask-RESTful api
Der Code selbst besteht aus einer main.py-Datei:
from flask import Flask, request from flask_restful import Resource, Api from flask_jwt_extended import JWTManager from flask_jwt_extended import create_access_token, jwt_required from flask_cors import CORS app = Flask(__name__) app.config['JWT_SECRET_KEY'] = 'my_cool_secret' jwt = JWTManager(app) CORS(app) api = Api(app) class UserLogin(Resource): def post(self): username = request.get_json()['username'] password = request.get_json()['password'] if username == 'admin' and password == 'habr': access_token = create_access_token(identity={ 'role': 'admin', }, expires_delta=False) result = {'token': access_token} return result return {'error': 'Invalid username and password'} class ProtectArea(Resource): @jwt_required def get(self): return {'answer': 42} api.add_resource(UserLogin, '/api/login/') api.add_resource(ProtectArea, '/api/protect-area/') if __name__ == '__main__': app.run(debug=True, host='0.0.0.0')
Lassen Sie uns den Code durchgehen:
- Unser Backend wird die gesamte Interaktion mit der Außenwelt nur über RESTful API ausführen, auch die Autorisierung im Admin-Panel erfolgt über RESTful API. Für diesen Zweck verfügt der Kolben über ein praktisches Modul: Flask-RESTful api
- Das Modul flask_jwt_extended dient zum Schutz der Routen, auf die nur nach Autorisierung zugegriffen werden kann. Hier ist nichts Heiliges, nur ein JWT-Token ( JSON Web Token ) wird zu jeder http-Anforderung hinzugefügt, anhand dessen unsere Anwendung erkennt, dass der Benutzer autorisiert ist.
Der obige Code zeigt, dass der Dekorator @jwt_required für diesen Zweck verwendet wird. Sie können es zu den API-Routen hinzufügen, die geschützt werden sollen. - Ohne flask_cors erhalten wir folgenden Fehler:
Access to XMLHttpRequest at 'http://localhost:5000/api/login/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Lesen Sie hier mehr über CORS .
Wir stellen alle notwendigen Bibliotheken zur Verfügung und führen den Code mit dem folgenden Befehl aus:
python main.py
Wie Sie sehen, habe ich den Benutzernamen und das Passwort für das Admin-Panel fest codiert: admin / habr.
Nachdem der Kolben gestartet wurde, können Sie seine Funktionalität mit dem Einrollen testen:
curl -X POST -H "Content-Type: application/json" -d '{"username": "admin", "password": "habr"}' localhost:5000/api/login/
Wenn ein solches Ergebnis:
{ "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIU...." }
Damit ist alles in Ordnung und Sie können nach vorne fahren.
Frontend React-Admin
Ich mochte reag-admin. Hier ist die
Dokumentation und hier ist die Demoversion:
https://marmelab.com/react-admin-demo/#/loginLogin: Demo
Passwort: Demo
Um dasselbe Admin-Panel wie in der Demo zu erhalten, führen wir die folgenden Befehle aus:
git clone https://github.com/marmelab/react-admin.git && cd react-admin && make install yarn add axios make build make run-demo
Jetzt müssen wir ihr beibringen, wie sie mit unserem Backend umgehen kann.
Ersetzen Sie dazu den Inhalt der
admin/examples/demo/src/authProvider.js
durch den folgenden Code, der für die Autorisierung, das Verlassen des Administratorfensters usw. verantwortlich ist:
admin / examples / demo / src / authProvider.js import { AUTH_LOGIN, AUTH_LOGOUT, AUTH_ERROR, AUTH_CHECK, AUTH_GET_PERMISSIONS } from 'react-admin'; import axios from 'axios'; import decodeJwt from 'jwt-decode'; export default (type, params) => { if (type === AUTH_LOGIN) { const { username, password } = params; let data = JSON.stringify({ username, password }); return axios.post('http://localhost:5000/api/login/', data, { headers: { 'Content-Type': 'application/json', } }).then(res => { if (res.data.error || res.status !== 200) { throw new Error(res.data.error); } else { const token = res.data.token; const decodedToken = decodeJwt(token); const role = decodedToken.identity.role; localStorage.setItem('token', token); localStorage.setItem('role', role); return Promise.resolve(); } }); } if (type === AUTH_LOGOUT) { localStorage.removeItem('token'); localStorage.removeItem('role'); return Promise.resolve(); } if (type === AUTH_ERROR) { const { status } = params; if (status === 401 || status === 403) { localStorage.removeItem('token'); localStorage.removeItem('role'); return Promise.reject(); } return Promise.resolve(); } if (type === AUTH_CHECK) { return localStorage.getItem('token') ? Promise.resolve() : Promise.reject({ redirectTo: '/login' }); } if (type === AUTH_GET_PERMISSIONS) { const role = localStorage.getItem('role'); return role ? Promise.resolve(role) : Promise.reject(); } };
Und jetzt wenden wir uns zum Spaß unserem Backend zu, der Route:
/api/protect-area/
und speichern das Ergebnis auf der Hauptadministrationsseite, auf der sich bärtige Männer befinden.
Ersetzen Sie dazu den Inhalt der Datei
react-admin/examples/demo/src/dashboard/Welcome.js
durch den folgenden Code:
admin / examples / demo / src / dashboard / Welcome.js import React, { useState, useEffect, useCallback } from 'react'; import axios from 'axios'; import Card from '@material-ui/core/Card'; import CardActions from '@material-ui/core/CardActions'; import CardContent from '@material-ui/core/CardContent'; import CardMedia from '@material-ui/core/CardMedia'; import Button from '@material-ui/core/Button'; import Typography from '@material-ui/core/Typography'; import HomeIcon from '@material-ui/icons/Home'; import CodeIcon from '@material-ui/icons/Code'; import { makeStyles } from '@material-ui/core/styles'; import { useTranslate } from 'react-admin'; const useStyles = makeStyles({ media: { height: '18em', }, }); const mediaUrl = `https://marmelab.com/posters/beard-${parseInt( Math.random() * 10, 10 ) + 1}.jpeg`; const Welcome = () => { const [state, setState] = useState({}); const fetchFlask = useCallback(async () => { axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token'); await axios.get('http://localhost:5000/api/protect-area/').then(res => { const answer = res.data.answer; setState({ answer }); }); }, []); useEffect(() => { fetchFlask(); }, []);
Gehe zur Adresse:
localhost:3000
Loggen Sie sich ein, indem Sie login / pass eingeben: admin / habr
Und wenn alle Regeln, dann sehen wir 42 in der Kopfzeile auf der Hauptseite.
Wie folgt:

Optional
- Neben Flask-RESTful gibt es auch Flask-RESTplus, hier können Sie sich die Diskussion ansehen, die besser oder schlechter ist
- Sie können ein Admin-Panel auf der Vorderseite schreiben und dann ausführen:
npm run build
- Sie erhalten fertige statische Dateien, die flask nur als Vorlage rendern kann. Weitere Details hier . Auf diese Weise müssen Sie den Webserver nicht mehr für die Ausführung der Reaktion verantwortlich machen.