Здравствуйте, сообщество! Это мой первый пост здесь, и в этом посте я хочу показать вам, как вы можете сделать простой клин Twitter клон с помощью React и Flask. Это будет серию 3 части и в этой части мы построим приложение.
Прежде чем начать, я предполагаю, что вы знаете колбу, реагировать, JavaScript, Python и HTML
Настройка проекта
Я буду использовать VSCode как My IDE, но вы можете использовать все, что вам нравится (Pycharm, Webstorm, Atom – некоторые примеры). Я покажу инструкции для моей IDE.
Создание нашего проекта
Создайте папку, которая будет размещать ваш проект и открыть окно терминала там. Мне нравится делать вещи, используя терминал Unix (Bash Shell), но вы можете использовать файловой проводник на основе GUI. Давайте создадим Backend
папка.
mkdir backend
Я буду использовать Create-raction-app
создать Frontend
Папка с приложением raction инициализировано.
npx create-react-app frontend
Теперь у вас должно быть 2 папки, интерфейсы и бэкэнда.
$ ls backend frontend
Хороший! Теперь давайте создадим бэкэнду. CD
в папку Backend и создайте виртуальную среду для колбы. Вы можете использовать Пипнв
Или не использовать виртуальную среду вообще!
python3 -m venv venv && . venv/bin/activate
Это должно создать виртуальную среду с именем Венв
и активировать его. Теперь CD
в нашу основную папку проекта и откройте его с помощью VSCode, набрав кода
.
Создание основного проекта колба
Теперь давайте создадим бэкэнду. Во-первых, нам нужно установить колбу.
pip install flask
Убедитесь, что ваш VirtualenV активирован
Теперь создайте файл с именем app.py
Отказ Это будет основной файл для нашей бэкинги.
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return "Hello, world!" if __name__ == "__main__": app.run(debug=True) # debug=True restarts the server everytime we make a change in our code
Теперь давайте запустим бэкэнда, набрав
python3 app.py
Давайте проверим, работает ли сервер. Вы можете посетить localhost: 5000 В вашем браузере или используйте Клиент отдыха
Как Бессонница если ты хочешь. Для тестирования методов пост я буду использовать Curl
, что является утилитой командной строки, но вы можете использовать клиент покоя GUI.
Для базы данных мы можем использовать что-то называемое Flask-Sqlalchemy
, что это Sqlalchemy
или SQLite3
для Колбу
Отказ Давайте сначала выключите наш сервер, нажав Ctrl + C
Чтобы завершить его и давайте установим Flask-Sqlalchemy
Отказ
pip install flask-sqlalchemy
Теперь, обратно в app.py
Давайте импомнем Flask-Sqlalchemy
Отказ
from flask_sqlalchemy import SQLAlchemy
И при том, где мы определили приложение
Напишите этот код:
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///twitter.db" # DB db = SQLAlchemy(app) class Users(db.Model): id = db.Column('student_id', db.Integer, primary_key = True) # primary_key makes it so that this value is unique and can be used to identify this record. username = db.Column(db.String(24)) email = db.Column(db.String(64)) pwd = db.Column(db.String(64)) # Constructor def __init__(self, username, email, pwd): self.username = username self.email = email self.pwd = pwd
Так что делает этот код, сначала он устанавливает наш файл базы данных AS Twitter.db
Отказ Вы можете изменить это имя, если хотите. Тогда Пользователи
Класс, который вы видите, это Модель
, который выкладывает, что твой Пользователи
Стол столбцы есть. Довольно стандартные материалы SQL.
Теперь, временно, выше вернуть
Заявление в Индекс
Функция Написать это:
db.create_all()
Ваш файл должен выглядеть так:
from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///twitter.db" # DB db = SQLAlchemy(app) class Users(db.Model): id = db.Column('student_id', db.Integer, primary_key = True) # primary_key makes it so that this value is unique and can be used to identify this record. username = db.Column(db.String(24)) email = db.Column(db.String(64)) pwd = db.Column(db.String(64)) # Constructor def __init__(self, username, email, pwd): self.username = username self.email = email self.pwd = pwd @app.route('/') def index(): return "Hello, world!" if __name__ == "__main__": app.run(debug=True)
Запустите сервер и посетите localhost: 5000 или выполнить Получить
Запрос, используя ваш любимый Отдых
клиент. Например, в Curl
Вы напечатаете
curl "http://localhost:5000"
И вы должны получить тот же ответ, но теперь, когда вы смотрите в папку, вы можете найти новый файл под названием Twitter.db
созданный. Это ваша база данных. В отличие от чего-то вроде MySQL
, Мариадб
или Монгодб
, SQLite
Не нужен сервер для функции.
Основные маршруты Crud
Теперь давайте выполним некоторые основные Круд
( C Reate R преступность Обновление Уничтожить) Действия, добавляя еще несколько маршрутов в наше приложение. Сначала удалите индекс маршрута целиком. Нам не нужно это не понадобиться. Я собираюсь префис все свои маршруты с /API. .
@app.route("/api/users", methods=["GET", "POST", "DELETE"]) def users(): method = request.method if (method.lower() == "get"): # READ users = Users.query.all() return jsonify([{"id": i.id, "username": i.username, "email": i.email, "password": i.pwd} for i in users]) # Get all values from db elif (method.lower() == "post"): # CREATE try: username = request.json["username"] email = request.json["email"] pwd = request.json["pwd"] if (username and pwd and email): # Checks if username, pwd or email are empty try: user = Users(username, email, pwd) # Creates a new record db.session.add(user) # Adds the record for committing db.session.commit() # Saves our changes return jsonify({"success": True}) except Exception as e: return ({"error": e}) else: return jsonify({"error": "Invalid form"}) # jsonify converts python vars to json except: return jsonify({"error": "Invalid form"}) elif (method.lower() == "delete"): # DESTROY try: uid = request.json["id"] if (uid): try: user = Users.query.get(uid) # Gets user with id = uid (because id is primary key) db.session.delete(user) # Delete the user db.session.commit() # Save return jsonify({"success": True}) except Exception as e: return jsonify({"error": e}) else: return jsonify({"error": "Invalid form"}) except: return jsonify({"error": "m"})
- Мы будем работать над методом положения немного позже * Теперь у нас есть маршрут в нашем приложении под названием
/API/пользователи
Отказ Мы можем выполнить создание, читать и уничтожать действия с помощью различных методов HTTP. Больше об этом здесь
Теперь это то, что наш код должен выглядеть:
from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///twitter.db" # DB db = SQLAlchemy(app) class Users(db.Model): id = db.Column('student_id', db.Integer, primary_key = True) # primary_key makes it so that this value is unique and can be used to identify this record. username = db.Column(db.String(24)) email = db.Column(db.String(64)) pwd = db.Column(db.String(64)) # Constructor def __init__(self, username, email, pwd): self.username = username self.email = email self.pwd = pwd # Routes # Users @app.route("/api/users", methods=["GET", "POST", "DELETE"]) def users(): method = request.method if (method.lower() == "get"): # READ users = Users.query.all() return jsonify([{"id": i.id, "username": i.username, "email": i.email, "password": i.pwd} for i in users]) # Get all values from db elif (method.lower() == "post"): # CREATE try: username = request.json["username"] email = request.json["email"] pwd = request.json["pwd"] if (username and pwd and email): # Checks if username, pwd or email are empty try: user = Users(username, email, pwd) # Creates a new record db.session.add(user) # Adds the record for committing db.session.commit() # Saves our changes return jsonify({"success": True}) except Exception as e: return ({"error": e}) else: return jsonify({"error": "Invalid form"}) # jsonify converts python vars to json except: return jsonify({"error": "Invalid form"}) elif (method.lower() == "delete"): # DESTROY try: uid = request.json["id"] if (uid): try: user = Users.query.get(uid) # Gets user with id = uid (because id is primary key) db.session.delete(user) # Delete the user db.session.commit() # Save return jsonify({"success": True}) except Exception as e: return jsonify({"error": e}) else: return jsonify({"error": "Invalid form"}) except: return jsonify({"error": "m"}) return ({"error": "Invalid form"}) except: return ({"error": "Invalid form"}) if __name__ == "__main__": app.run(debug=True)
Давайте дадим этого человека тест-драйв! Во-первых, давайте выполним Получить
Запрос на /API/пользователи
Отказ
curl "http://localhost:5000/api/users" # OUTPUT: []
Мы получаем пустой массив, потому что база данных не имеет данных
Теперь давайте дадим ему некоторые данные. Выполнить Пост
Запрос на /API/пользователи
с некоторыми данными.
curl -X POST -H "Content-Type: application/json" -d '{"username": "foo", "email": "foo@bar.com", "pwd": "bar"}' "http://localhost:5000/api/users"
Если вы Получить
Снова данные, вы можете заметить, что запись была сделана. Теперь давайте удалим пользователь
curl -X DELETE -H "Content-Type: application/json" -d '{"id": 1}' "http://localhost:5000/api/users"
И если мы запрашиваем данные, мы должны вернуть пустую строку! Мы сделаем Поставить
позже.
И это должно быть (на данный момент) для нашей колбы. Идите вперед и остановите сервер ( ^ C
)
Создание интерфейса
Теперь давайте сосредоточимся на Frontend. Открыть Frontend
Папка (или что вы его назвали) в терминале и введите:
npm start
Это должно открыть веб-страницу в localhost: 3000 И вы должны увидеть это:
Создание домашней страницы
Шаблон по умолчанию Create-raction-app
Дает нам не то, что нам нужно, так что давайте удалим содержание нашего публичный
и SRC
папка. Вы увидите ваше приложение, но это нормально. Также создать Public/index.html
, SRC/index.js
, SRC/Компоненты
, SRC/Компоненты/app.jsx
, SRC/Компоненты/home.jsx
, SRC/Компоненты/Navbar.jsx
rm -r public/* src/* mkdir src/components touch public/index.html src/index.js src/components/App.jsx src/components/Home.jsx src/components/Navbar.jsx
Теперь давайте установим код для index.html
Quickr
я использую W3css. Для моего CSS стайлинга, как это быстро и легко использовать
Теперь для всех файлов JavaScript:
// src/index.js import React from "react"; import ReactDOM from "react-dom"; import App from "./components/App"; ReactDOM.render(, document.getElementById("root"));
// src/components/App.jsx import React from "react"; import Home from "./Home"; import Navbar from "./Navbar"; function App() { return (); } export default App;
// src/components/Home.jsx import React from "react"; function Home() { return (); } export default Home; Quickr - Quick Twitter
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer consectetur libero nibh, non sodales urna malesuada nec. Sed tortor eros, blandit eget fringilla at, gravida a nibh. Etiam dui nulla, aliquam vitae purus a, auctor malesuada arcu. Vestibulum venenatis orci nisl, sed elementum leo tincidunt eget. Nullam convallis nisi in.
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer consectetur libero nibh, non sodales urna malesuada nec. Sed tortor eros, blandit eget fringilla at, gravida a nibh. Etiam dui nulla, aliquam vitae purus a, auctor malesuada arcu. Vestibulum venenatis orci nisl, sed elementum leo tincidunt eget. Nullam convallis nisi in.
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer consectetur libero nibh, non sodales urna malesuada nec. Sed tortor eros, blandit eget fringilla at, gravida a nibh. Etiam dui nulla, aliquam vitae purus a, auctor malesuada arcu. Vestibulum venenatis orci nisl, sed elementum leo tincidunt eget. Nullam convallis nisi in.
// src/components/Navbar.jsx import React from "react"; function Navbar() { return ( ); } export default Navbar;
И, наконец, ваш сайт должен выглядеть так:
Теперь давайте добавим некоторую функциональность!
Подключение бэкэнда к Frontend
Теперь давайте внедрем в систему и зарегистрироваться. Помните маршруты, которые мы сделали ранее? Давайте преобразуем их в функции
def getUsers(): users = Users.query.all() return [{"id": i.id, "username": i.username, "email": i.email, "password": i.pwd} for i in users] def addUser(username, email, pwd): if (username and pwd and email): try: user = Users(username, email, pwd) db.session.add(user) db.session.commit() return True except Exception as e: print(e) return False else: return False def removeUser(uid): uid = request.json["id"] if (uid): try: user = Users.query.get(uid) db.session.delete(user) db.session.commit() return True except Exception as e: print(e) return False else: return False
Теперь давайте добавим логин и регистрируйте маршрут API. Я собираюсь префикс мои маршруты с /API.
как раньше.
@app.route("/api/login", methods=["POST"]) def login(): try: email = request.json["email"] password = request.json["pwd"] if (email and password): users = getUsers() # Check if user exists return jsonify(len(list(filter(lambda x: x["email"] == email and x["password"] == password, users))) == 1) else: return jsonify({"error": "Invalid form"}) except: return jsonify({"error": "Invalid form"}) @app.route("/api/register", methods=["POST"]) def register(): try: email = request.json["email"] email = email.lower() password = request.json["pwd"] username = request.json["username"] # Check to see if user already exists users = getUsers() if(len(list(filter(lambda x: x["email"] == email, users))) == 1): return jsonify({"error": "Invalid form"}) # Email validation check if not re.match(r"[\w\._]{5,}@\w{3,}.\w{2,4}", email): return jsonify({"error": "Invalid form"}) addUser(username, email, password) return jsonify({"success": True}) except: return jsonify({"error": "Invalid form"})
В нашем методе регистрации у нас есть некоторая проверка формы. Он проверяет, уже зарегистрирован ли электронное письмо, и если электронная почта является действительным электронным письмом. Теперь давайте проверим это. Запустите свой сервер и сделайте несколько запросов.
# REGISTER curl -X POST -H "Content-Type: application/json" -d '{"email": "foo@bar.dev", "pwd": "foobar", "username": "foobar"}' "http://localhost:5000/api/register"
# LOGIN curl -X POST -H "Content-Type: application/json" -d '{"email": "azeez@man.com", "pwd": "azeez"}' "http://localhost:5000/api/login"
Итак, теперь мы можем войти в нашу базу данных с помощью CLI. Но нам нужно разрешить пользователям войти в систему, используя веб-сайт. Давайте отправимся на интерфейс.
Итак, я сделал 2 файла, Login.jsx
и Jesge.jsx.
. Эти файлы содержат вход и регистрируйте форму отдельно. Вы можете использовать свою собственную разметку, но для тех, кто хочет использовать мой, здесь вы идете:
// src/components/Login.jsx import React, { Component } from "react"; class Login extends Component { render() { return (); } } export default Login;LOGIN
// src/components/Register.jsx import React, { Component } from "react"; class Register extends Component { render() { return (); } } export default Register;REGISTER
Хорошо, мы закончили с нашей разметкой, но, как мы можем сделать его в другом маршруте? Например, если я ввожу https://mywebsite.com/login
Мне нужно увидеть страницу входа в систему. Это можно сделать с помощью React-Router-DOM
Отказ Первый, Установить React-Router-DOM
npm i react-router-dom
И, теперь, давайте реализуем это в нашем App.jsx.
// src/components/App.jsx import React from "react"; import Home from "./Home"; import Navbar from "./Navbar"; import Login from "./Login"; import Register from "./Register"; import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; function App() { return (); } export default App;
Я также обновил маршруты в Navbar.jsx
Отказ
// src/components/Navbar.jsx import React from "react"; function Navbar() { return ( ); } export default Navbar;
Теперь, когда вы нажимаете на кнопки входа в систему и регистрируйте в NAVBAR, вы должны увидеть созданные компоненты. Теперь давайте добавим некоторые функциональные возможности к компонентам.
Авторизоваться
Во-первых, давайте установим что-то называемое Axios.
.
npm i axios
Теперь добавим функцию, которая отправляет Пост
запрос на бэкэнду.
// Login.jsx import React, { Component } from "react"; import axios from "axios"; class Login extends Component { login = (e) => { e.preventDefault(); axios .post("http://localhost:5000/api/login", { email: document.getElementById("email").value, pwd: document.getElementById("password").value, }) .then((res) => { console.log(res.data); }); }; render() { return (); } } export default Login;LOGIN
import React, { Component } from "react"; import axios from "axios"; class Register extends Component { register = (e) => { e.preventDefault(); axios .post("http://localhost:5000/api/register", { email: document.getElementById("email").value, username: document.getElementById("username").value, pwd: document.getElementById("password").value, }) .then((res) => { console.log(res.data); }); }; render() { return (); } } export default Register;REGISTER
Итак, что мы здесь делаем, есть всякий раз, когда форма представлена форма, мы отправляем запрос на бэкэну к маршрутам входа и регистрации. И когда мы получаем ответ, мы регистрируем его. Теперь введите некоторые мусорные данные в регистре, и откройте консоль в браузере (или devtools), нажав Ctrl + Shift + I
Для Windows/Linux или CMD + опция + I
для Mac. Нажмите кнопку «Регистрация» и в консоли, вы должны увидеть такой ошибку:
Теперь эта ошибка – это мера безопасности, помещающаяся чем-то, называемое CORS. Чтобы обойти это, нам нужно установить что-то называемое Flask-Cors
на нашей части.
pip install flask-cors
Теперь измените начало вашего app.py
к этому:
from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy from flask_cors import CORS import re app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///twitter.db" CORS(app) # ...
Если вы теперь нажмете регистр, вы должны увидеть {Успех: правда}
в консоли. И теперь, если мы войдем в систему, используя тот же адрес электронной почты и пароль, вы можете увидеть правда
В консоли, то есть все работает! Теперь давайте дадим пользователю некоторые отзывы. Создайте новый файл под названием Alert.jsx
и поставить это в это:
import React from "react"; function Alert(props) { return ({props.message}); } export default Alert;
Оповещение
Теперь есть многоразовый компонент, который мы можем использовать в любом месте нашего кода, и мы можем дать ему сообщение. Это отобразит это сообщение на красном фоне и в красном тексте. Мы можем использовать этот компонент в Jesge.jsx
:
import React, { Component } from "react"; import axios from "axios"; import Alert from "./Alert"; class Register extends Component { state = { err: "" }; register = (e) => { e.preventDefault(); axios .post("http://localhost:5000/api/register", { email: document.getElementById("email").value, username: document.getElementById("username").value, pwd: document.getElementById("password").value, }) .then((res) => { if (res.data.error) { this.setState({ err: res.data.error }); } else { this.setState({ register: true }); } }); }; render() { return (); } } export default Register;REGISTER{this.state.err.length > 0 && ()}
Теперь, если мы введем неверное электронное письмо, (действительное электронное письмо, в соответствии с моим Regex, это то, что имеет 5 или более буквенных персонажей, в том числе. и _, @, 3 или более буквенно-цифровых символов, а. и 2-4 больше буквенно-цифровых символов), мы должны получить это:
Потрясающий! Login.jsx
Также можно использовать некоторую обработку ошибок.
import React, { Component } from "react"; import axios from "axios"; import Alert from "./Alert"; class Login extends Component { state = { err: "" }; login = (e) => { e.preventDefault(); axios .post("http://localhost:5000/api/login", { email: document.getElementById("email").value, pwd: document.getElementById("password").value, }) .then((res) => { if (res.data.error) { this.setState({ err: res.data.error }); } else { this.setState({ login: true }); } }); }; render() { return (); } } export default Login;LOGIN{this.state.err.length > 0 && ()}
И теперь, если мы введем неправильные полномочия, мы должны получить это:
Вывод
Хороший! Теперь вы узнали, как подключить колбу и реагировать вместе с помощью RESTFLAY API. В следующей части мы добавим возможность публиковать и увидеть твиты. Этот пост был довольно долго. Я постараюсь сделать видео на YouTube об этом, и если я сделаю, я обязательно свяжу это здесь. Весь код доступен на Гадость . Это было довольно долго для первого поста!
Часть вторая сейчас!
Оригинал: “https://dev.to/arnu515/build-a-fullstack-twitter-clone-using-flask-and-react-1j72”