Рубрики
Без рубрики

Построить полный клон Twitter, используя колбу и реагировать | Часть 1.

Здравствуйте, сообщество! Это мой первый пост здесь, и в этом посте я хочу показать вам, как вы можете сделать Si … Теги от реагирования, Python, учебник, WebDev.

Здравствуйте, сообщество! Это мой первый пост здесь, и в этом посте я хочу показать вам, как вы можете сделать простой клин 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 (
        
            

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.

); } export default Home;
// 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 (
            
LOGIN

); } } export default Login;
// src/components/Register.jsx
import React, { Component } from "react";

class Register extends Component {
    render() {
        return (
            
REGISTER

); } } export default 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 (
            
LOGIN

); } } export default 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 (
            
REGISTER

); } } export default 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 (
            
REGISTER
{this.state.err.length > 0 && ( )}

{this.state.register &&

You're registered!

}

); } } export default Register;

Теперь, если мы введем неверное электронное письмо, (действительное электронное письмо, в соответствии с моим 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 (
            
LOGIN
{this.state.err.length > 0 && ( )}

{this.state.register &&

You're logged in!

}

); } } export default Login;

И теперь, если мы введем неправильные полномочия, мы должны получить это:

Вывод

Хороший! Теперь вы узнали, как подключить колбу и реагировать вместе с помощью RESTFLAY API. В следующей части мы добавим возможность публиковать и увидеть твиты. Этот пост был довольно долго. Я постараюсь сделать видео на YouTube об этом, и если я сделаю, я обязательно свяжу это здесь. Весь код доступен на Гадость . Это было довольно долго для первого поста!

Часть вторая сейчас!

Оригинал: “https://dev.to/arnu515/build-a-fullstack-twitter-clone-using-flask-and-react-1j72”