Arbeiten mit einer Datenbank in Flask: von Juni bis Juni

Ich wurde inspiriert, diesen Artikel zu schreiben, weil ich den gleichen Neulingen in Python im Allgemeinen helfen und mit Flask im Besonderen arbeiten wollte, wie ich selbst. Während wir an der Aufgabe einer ganzheitlichen und verständlichen Erklärung in dem Stil arbeiteten, den wir Neulinge nicht fanden, wie. Ich musste Stück für Stück nach Informationen suchen. Es werden keine Bilder angezeigt. Ein rein technischer Artikel. Erfahrene Personen sind für Kommentare und Tipps zur Verbesserung des Codes dankbar.

Also lasst uns anfangen.

Ich habe gleich nach Neujahr angefangen, Python zu lernen. Nach vier Monaten wurde mir klar, dass die Theorie, neben dem Training in fiktiven Aufgaben, die nicht in die Arbeit gehen, Sie nicht besonders lernen werden, ich mich entschied, nach "Kampf" -Aufgaben zu suchen. Dazu fragte ich meine Freunde, ob sie echte Aufgaben hätten, die programmiert werden müssten. Ein "Freund meines Freundes" bat mich, einen Bot für Telegramm zu implementieren (ich vermisse die Essenz des Bots; es spielt keine Rolle - ich musste jede Aufgabe, die einen bestimmten Kunden hat, übernehmen und nach Kundenwunsch implementieren).

Auf der Suche nach einer Lösung habe ich natürlich als erstes mit den bekannten Frameworks Python Telegram Bot und pyTelegramBotAPI begonnen.. Als Anfänger schien es mir zunächst nur ein Fund zu sein - insbesondere ohne die Nuancen des Codes zu verstehen, war es möglich, schnell mit dem „Sägen“ des echten Bots zu beginnen. Einige Tage lang bin ich auf die Tatsache gestoßen, dass ich nicht die Funktionen erstellen kann, die ich benötige. Es scheint, dass er alles gemäß der Dokumentation getan hat, aber es wurde nicht entschieden. Dann wurde mir klar, dass ich überhaupt nicht verstand, wie das Framework „unter der Haube“ funktioniert und warum etwas, das funktionieren sollte, bei mir nicht funktioniert. wo und welche Befehle sollen mit welchen Methoden aufgerufen werden. Im Allgemeinen habe ich mich entschlossen, das Framework beiseite zu legen und zu versuchen, besser zu verstehen, wie die Telegramm-API selbst funktioniert und wie Sie direkt damit arbeiten können, wodurch ich mehr Kontrolle über die Situation habe und die gesamte Küche der Arbeit mit der API genauer studieren kann. Es ist möglich, dass ich nicht mehr auf die Frameworks Python Telegram Bot und pyTelegramBotAPI zurückgreifen werde.Oder ich komme zurück, um meine Arbeit an der Erstellung meines eigenen Fahrrads mit der Telegramm-API zu vereinfachen. Aber selbst wenn ich zurückkomme, werde ich viel mehr über die Arbeit dieser Frameworks verstehen.

Ich hatte einen nicht überprüften kleinen Kurs über Udemy, nur um einen Bot für Telegram zu erstellen. Zum Zeitpunkt dieses Schreibens war dies der einzige Udemy-Kurs, in dem eine Person ein Problem ohne den Python-Telegramm-Bot und pyTelegramBotAPI lösen würde (ich gebe keinen Link an, damit dies keine Werbung ist). Um es zu lösen, benutzte er Flask. Hier hatte ich übrigens nach einem bestimmten „militärischen Weg“ die Gelegenheit, meinen Kurs zu diesem Thema aufzuschreiben, obwohl es natürlich zu früh ist - ich werde keinen besonderen Wert bringen. Wenn Sie als erfahrener Programmierer, der diesen Artikel liest, viel darüber wissen, können Sie Ihren eigenen Kurs erstellen. Gerne kaufe ich ihn für 10,99 USD (ein typischer Rabattpreis für Udemy) bei Ihnen, um etwas Neues zu lernen.

Im Allgemeinen wurde mir während des Kurses klar, dass Flask es mir ermöglichen wird, die Bearbeitung von GET- und POST-Anfragen zu vereinfachen.

Da dieser Artikel speziell der Arbeit mit der Datenbank gewidmet ist, werde ich darüber sprechen. Es ist jedoch immer wieder verlockend, andere Feinheiten zu beschreiben, z. B.: Übertragen der Verbindungseinstellungen in eine "geheime" Datei, Empfangen und Verarbeiten von Daten, die von der Telegramm-API empfangen wurden, sowie Empfangen von Webhooks von Telegram auf einem lokalen Computer ohne SSL-Zertifikat. Wenn Sie Interesse haben, lassen Sie es mich wissen und ich werde einen separaten Artikel schreiben.

Ungefähr drei bis vier Tage meiner Juni-Zeit brauchte ich, um zu verstehen, dass ich mich vom Framework entfernen musste, bevor ich sicher Daten aus dem Telegramm empfangen, den Text verarbeiten (analysieren) und abhängig davon Was der Benutzer geschrieben hat, senden Sie ihm die erforderlichen Befehle sowie Schaltflächen (einschließlich Überschreiben der Nachricht und Ändern der Schaltflächen).

Der nächste Schritt für mich war, die Datenbank zu verbinden, um Benutzer zu speichern, die mit dem Bot darin arbeiten, sowie Daten über ihre Interaktion im Bot als Teil der Aufgabe, mit der er konfrontiert war.

Das erste, was ich in Google gemacht habe, war ein Artikel von Habré mit einer Übersetzung des Mega-Lehrbuchs Miguel Grinberg (das Original seines Blogs ist hier ).

Das vierte Kapitel befasst sich mit der Verbindung zu einer Datenbank mithilfe von Flask und SQLAlchemy ORM. Dann dachte ich: "Wow, wie cool, jetzt ist das Problem gelöst." Seltsamerweise funktionierte die vom Autor vorgeschlagene Dateistruktur bei mir nicht.

Ich tat analog wie er:

microblog\
  venv\
  app\
    __init__.py
    models.py
  main.py

In main.py erledige ich die gesamte Hauptarbeit mit der Telegramm-API.
In app \ models.py erstelle ich Klassen für die Datenbank.
In der App \ __ init__.py wurde alles so gemacht, wie Miguel Grinberg schrieb.

Aber aus irgendeinem Grund wollten sie mich in main.py nicht aus dem App-Import db, app ziehen. Verbrachte ungefähr eine Stunde damit, nach Problemen und Lösungen im Internet zu suchen. Infolgedessen stieß Oleg Molchanov auf einen YouTube-Kanal und sein Video „Erstellen eines Blogs auf einer Flasche (Lektionen) - Erstellen von Posts (Modellen) und SQLAlchemy“. Dort habe ich beobachtet, wie er eine Verbindung zur Datenbank herstellt, und versucht, diesen Weg zu gehen (ohne die Datei models.py in das App-Verzeichnis zu stellen, ohne __init__.py zu erstellen.

Im Allgemeinen ist die Struktur meines Projekts jetzt einfach zu blamieren (und ein wenig hässlich, was mich vielleicht verwirrt In Zukunft werde ich verstehen, wie man die Struktur verbessert.

Bild

Wie Sie sehen können, habe ich app.py, models.py, main.py, app.sqlite (der Rest der Dateien bezieht sich nicht auf das aktuelle Thema).

In app.py habe ich diesen Code:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from config import Config

app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)

In models.py:

from datetime import datetime
from app import db

class Users(db.Model):
    #   
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(120), index=True, unique=True)
    last_name = db.Column(db.String(128))
    first_name = db.Column(db.String(128))
    created = db.Column(db.DateTime, default=datetime.now())
    tasks = db.relationship('Tasks', backref='tasks')

    #     
    # def __init__(self, *args, **kwargs):
    #     super(Users, self).__init__(*args, **kwargs)

    def __init__(self, username, last_name, first_name):
        self.username = username
        self.last_name = last_name
        self.first_name = first_name

    def __repr__(self):
        return '<User {}>'.format(self.username)


class Tasks(db.Model):
    #    
    __tablename__ = 'tasks'
    id = db.Column(db.Integer, primary_key=True)
    owner_id = db.Column(db.Integer(), db.ForeignKey('users.id'))
    name = db.Column(db.String(120), index=True)
    start = db.Column(db.Boolean, default=False)
    finish = db.Column(db.Boolean, default=False)
    created_on = db.Column(db.DateTime, default=datetime.now())
    updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow)

    #     
    def __init__(self, *args, **kwargs):
        super(Tasks, self).__init__(*args, **kwargs)

    # def __init__(self, name, last_name, first_name):
    #     self.name = name
    #     self.last_name = last_name
    #     self.first_name = first_name

    def __repr__(self):
        return '<Tasks {}>'.format(self.name)

In config.py:

import os
from dotenv import load_dotenv
load_dotenv()

basedir = os.path.abspath(os.path.dirname(__file__))


#    
class Config(object):
    DEBUG = True
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
    # SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://{user}:{pw}@{url}/{db}'.format(user=os.environ.get('POSTGRES_USER'),
    #                                                                                 pw=os.environ.get('POSTGRES_PW'),
    #                                                                                 url=os.environ.get('POSTGRES_URL'),
    #
    #                                                                                 db=os.environ.get('POSTGRES_DB'))
    SQLALCHEMY_DATABASE_URI = (os.environ.get('DATABASE_URL') or
                               'sqlite:///' + os.path.join(basedir, 'app.sqlite')) + '?check_same_thread=False'
    SQLALCHEMY_TRACK_MODIFICATIONS = False  # silence the deprecation warning

Wie Sie bereits verstanden haben, habe ich aus den Einstellungen die direkten Werte für die Verbindung entfernt und sie in .env gerendert, damit sie nicht auf dem Produkt oder in SVN leuchten.

Zuerst wurde mir app.db (wo sich jetzt app.sqlite befindet) in SQLALCHEMY_DATABASE_URI als Datenbank geschrieben. Ja, ja, und aufgeschrieben, wie in der Anleitung Miguel Grinberg angegeben. Ich hoffe, Sie verstehen, dass Sie es durch .sqlite ersetzen müssen. Vorher dachte ich an eine Stunde nach schmerzhaften Versuchen, den Code auszuführen.

Sie können Datenbanken und Tabellen in SQLite erstellen, indem Sie zur Debugging-Konsole gehen (z. B. in PyCharm habe ich Tools -> Python oder Debug Console:

Bild

Hier verbinden wir zuerst die Methode, die wir benötigen, in der gewünschten Datei (ich habe sie von Models import db) und geben nach erfolgreicher Verbindung den Befehl db.create_all () an. Danach wird eine Datenbank mit allen notwendigen Tabellen erstellt. Es ist wichtig zu wissen, dass die Datenbankdatei erstellt wird, wenn ich aus der App db importiere und den Befehl db.create_all () ausführe, aber es ist eine Art Unsinn, nicht die Datenbank (ich habe nicht verstanden, warum).

Als ich dieses Problem löste, dachte ich wieder, dass es jetzt keine Schwierigkeiten mehr gibt. Es bleibt nur eine Funktion für main.py zu schreiben, die unter bestimmten Umständen Daten aus dem Telegramm in die Datenbank schreibt. Nun, ich habe von Models Import Users verbunden und an der richtigen Stelle die Funktion aufgerufen:

try:
    find_user_in_db(username, first_name, last_name)
except NameError:
    print("user  ")
except:
    print("An exception occurred")

def add_users_to_db(username, last_name, first_name):
    """
        
    :return:
    """
    data = Users(username, last_name, first_name)
    db.session.add(data)
    db.session.commit()

def find_user_in_db(username, first_name, last_name):
    """
               
    :param username:
    :param first_name:
    :param last_name:
    :return:
    """
    user = db.session.query(Users).filter(Users.username == f'{username}').all()
    if not user:
        add_users_to_db(username, first_name, last_name)

In der letzten Funktion stand first anstelle von user = db.session.query (Users) .filter (Users.username == f '{username}'). First_or_404 () stand Users.query.filter_by (username = '{username}'). first_or_404 (). Hier habe ich auch ungefähr eine halbe Stunde gebraucht, um zu verstehen, dass diese Abfrage in der Datenbank nicht funktioniert und keine Daten empfängt, sodass die Abfrage an die Datenbank nicht gesendet wird. Google hat einen kleinen Artikel veröffentlicht, in dem die Leute sagten, es sei besser, db.session.query (Benutzer) zu verwenden. Warum so, ich xs, verschwendete keine Zeit mit der Analyse. Danach wurden die Daten in die Datenbank geschrieben.

Damit ist dieser Artikel abgeschlossen, da ich beschrieben habe, was ich beschreiben wollte, und das Problem der Verbindung der Datenbank mit Flask gelöst habe.

Dieser Artikel wurde nur aus dem Grund geschrieben, dass wir „June“ beim Lesen von Anweisungen lieben. Ich selbst habe auch versucht, Anweisungen zum Verbinden der Datenbank mit Flask zu finden. Ich fand keine vollständigen Anweisungen, also musste ich mich durch die Hindernisse bewegen. Nun, ich habe beschlossen, meine Erfahrung als die nächste zu beschreiben, die nach vorgefertigten Anweisungen suchen wird.

PS Wer nach einer vorgefertigten Lösung sucht, dann frage ich das Repository auf GitHub

PSS. Ich bin froh, wenn jemand eine Codeüberprüfung durchführt und seine Verbesserungsvorschläge gibt.

Vielen Dank für Ihre Aufmerksamkeit.

All Articles