Konvertieren einer SQLAlchemy MariaDb / MySQL Datenbank mit Integer Primary Keys in UUID Primary Keys für eine Flask Website
Erstellen Sie Skripte, um die Konvertierung zu automatisieren. Sie ersparen Ihnen Zeit und verhindern unnötige Fehler.
Diese Website verwendet Flask, (einfach) SQLAlchemy mit Alembic für Migrationen und MariaDb. Wenn Sie diese nicht verwenden, ist dieser Beitrag wahrscheinlich nicht das, was Sie suchen.
In einem früheren Beitrag habe ich geschrieben, warum viele Websites UUID Primary Keys anstelle von Integer Primary Keys verwenden sollten. Selbst wenn Sie eine hochleistungsfähige Website haben, sind wahrscheinlich nur wenige Tabellen für diese Leistung verantwortlich. Hochleistungs-Websites verwenden Caching, was bedeutet, dass (in den meisten Fällen) SELECT Leistungsunterschiede nicht zu Unterschieden in der Seitenreaktionszeit führen.
Das Hauptproblem bei der Verwendung von UUID Primary Keys ist die Leistung von INSERT bei Tabellen mit vielen Datensätzen. Die Neuberechnung der Schlüssel nach einem INSERT ist weitaus zeitaufwändiger als bei Verwendung von Integer Primary Keys. Für diese Website zeichne ich jede Anfrage in einer Datenbanktabelle page_request auf, auch eine Ansicht eines Blog-Posts wird in einer Tabelle content_item_view aufgezeichnet. Beide Tabellen müssen die maximale Leistung von INSERT aufweisen. Die anderen Tabellen haben nicht so viele Datensätze. Diese beiden Tabellen und einige Demo-Tabellen sind die einzigen Tabellen, die ich nicht konvertiert habe. Die Gesamtzahl der Tabellen in der Datenbank beträgt 80. Alle haben die Id-Spalte, die umgesetzt werden muß, vielleicht die Hälfte (?) verwendet nicht Foreign Keys.
Sollten Sie die Datenbank Ihrer Website konvertieren? Wahrscheinlich nicht, wenn sie gut läuft und Sie zufrieden sind. Ich wollte zu UUIDs konvertieren, also lesen Sie diesen Beitrag weiter, wenn Sie das auch wollen. Funktioniert die beschriebene Methode? Ja. Dieser Beitrag wurde auf der neuen (konvertierten) Datenbank geschrieben.
Automatisieren der Konvertierung der bestehenden Datenbank
Es gibt zwei wichtige Gründe, die Konvertierung zu automatisieren:
- Minimale Ausfallzeit der produktiven Website
- Vermeiden von Fehlern
Der Prozess zur Überführung der konvertierten Datenbank in die Produktion sieht in etwa so aus:
- Website abbauen
- Erstellen Sie eine Kopie der vorhandenen Datenbank
- Datenbank in ein anderes (lokales) System kopieren
- Datenbank konvertieren
- Kopieren der konvertierten Datenbank in das Produktivsystem
- Neue Software-Version aktivieren
- Website aufrufen
Die Zeit für die Konvertierung der Datenbank sollte so kurz wie möglich gehalten werden, ja, sie muss sogar automatisiert werden, weil wir auch Fehler vermeiden wollen. Ein Skript, das die Konvertierung durchführt, kann dies für Sie erledigen. Sie können dieses Skript so lange vorbereiten und testen, wie Sie wollen. Sobald Sie wissen, dass es einwandfrei funktioniert, sind Sie bereit für die Konvertierung der Produktionsdatenbank.
Ich habe auch zwei weitere Skripte entwickelt, siehe auch unten:
- Tabellen und Spalten vergleichen
- Kopieren von Daten von einer Datenbank in eine andere
Die Konvertierung der Datenbank erfolgt in vier Schritten
Machen Sie vor allem Sicherungen Ihrer Datenbank und überprüfen Sie durch Wiederherstellen und Testen, ob diese Sicherungsdatenbank korrekt ist! Sie wollen keine Daten verlieren. Die vier Schritte sind:
- Konvertieren Sie die vorhandene Datenbank in eine neue Datenbank DB_DATA mit UUIDs
Diese Datenbank enthält die Daten. Wir kümmern uns nicht um Einschränkungen, wir entfernen sie sogar alle. Das bedeutet, dass in der neuen Datenbank Foreign Keys nur Werte sind. Die wichtigsten Dinge, die wir hier tun, sind: Integer Primary Keys in UUID Primary Keys umwandeln und Integer Foreign Keys in UUID Foreign Keys umwandeln. - Generieren Sie eine Datenbank DB_FINAL mit Alembic mit UUIDs
. Diese Datenbank hat die UUID Primary Keys, UUID Foreign Keys und Beziehungen. Aber sie hat noch keine Daten ... noch nicht. Ich habe einen neuen Baum oder eine neue Version der Software erstellt. Hier nehme ich alle Änderungen vor, um UUID Primary Keys anstelle von Integer Primary Keys zu behandeln. In dieser neuen Version habe ich Änderungen an der Datei models.py vorgenommen: Integer Primary Keys bis UUID Primary Keys, Integer Foreign Keys bis UUID Foreign Keys - Vergleichen Sie die Datenbanktabellen und Spalten der Datenbank DB_DATA mit den Datenbanktabellen und Spalten der Datenbank DB_FINAL
Wir vergleichen keine Constraints. Sie MÜSSEN identisch sein, sonst können wir die Daten im nächsten Schritt nicht kopieren! - Kopieren Sie die Datenbanktabellendaten von DB_DATA in die Datenbanktabellen von DB_FINAL
. Ich mache dies mit SELECT INTO OUTFILE und LOAD DATA INFILE.
Einige Worte über den Code
Der zeitaufwendigste Teil, den ich entwickeln musste, war die Datenbankklasse. Diese enthält hauptsächlich MariaDb / MySQL administrative Methoden. Ich werde nicht meinen gesamten Code zeigen, aber um Ihnen einen Eindruck zu vermitteln, hier ist die Datenbankklasse mit einigen Methoden:
import pymysql.cursors
import uuid
class Database:
def __init__(self, user=None, passwd=None, host=None, db=None, charset=None, autocommit=None, connect_timeout=None):
...
def set_foreign_key_checks(self, off_on):
def table_get_constraints(self, table_name):
def table_has_integer_primary_key_id(self, table_name):
def table_create_column(self, table_name, column_definition):
def table_column_add_key(self, table_name, column_name):
def table_drop_column(self, table_name, column_name):
def table_drop_constraint(self, table_name, constraint_name):
def load_column_with_uuids(self, table_name, column_name, force=False):
def get_all_foreign_keys_to_table(self, table_name, column_name=None):
def select_into_outfile(self, outfile, table_name, column_names):
def load_from_infile(self, infile, table_name, column_names):
def copy_uuid_from_referenced_table_to_foreign_key_table(self,
referenced_table_name, referenced_table_column_name,
foreign_key_table_name, foreign_key_table_column_name,
from_referenced_table_column_name, to_foreign_key_table_column_name):
1. Konvertieren Sie die vorhandene Datenbank in eine neue Datenbank DB_DATA mit UUIDs
Wir müssen eine neue Datenbank mit UUIDs an den richtigen Stellen erstellen. Das bedeutet, dass wir Integer Primary Keys und Integer Foreign Keys in UUIDs konvertieren müssen. Nachdem wir UUID Foreign Keys erstellt haben, können wir die Einschränkungen fallen lassen.
Dies macht es einfach, Spalten umzubenennen.
Das Erstellen einer Spalte UUID Primary Key ist kein großes Problem. Ich erstelle eine CHAR(32)-Spalte 'id_upk_copy' und lade sie mit UUIDs. Um Foreign Keys zu behandeln, können wir die Tabelle INFORMATION_SCHEMA verwenden, um alle Foreign Keys in eine Tabelle zu bekommen. Unten sehen Sie ein Beispiel für die Tabelle Foreign Keys , die sich auf die Spalte id der Tabelle user bezieht. Die Abfrage lautet:
SELECT
TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
REFERENCED_TABLE_SCHEMA = 'peterspython_dev_existing'
AND
REFERENCED_TABLE_NAME = 'user';
Und das Ergebnis ist:
+---------------------+-------------+----------------------------+-----------------------+------------------------+
| TABLE_NAME | COLUMN_NAME | CONSTRAINT_NAME | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME |
+---------------------+-------------+----------------------------+-----------------------+------------------------+
| ... | ... | ... | user | id |
| user_mtm_user_group | user_id | user_mtm_user_group_ibfk_1 | user | id |
| user_mtm_user_role | user_id | user_mtm_user_role_ibfk_1 | user | id |
| user_login | user_id | user_login_ibfk_1 | user | id |
| comment | user_id | comment_ibfk_3 | user | id |
| contact_form | user_id | contact_form_ibfk_2 | user | id |
| ... | ... | ... | user | id |
+---------------------+-------------+----------------------------+-----------------------+------------------------+
Das Ergebnis enthält alles, was wir zur Konvertierung von Foreign Keys benötigen. Die Tabellen 'user_mtm_user_group' und 'user_mtm_user_role' sind die Beziehungstabellen many-to-many _role . Was ich tue, ist, für jedes Constraint
- Erstellen einer neuen Spalte user_id_ufk_copy
- Kopieren Sie die Spalte UUID aus der Spalte REFERENCED_TABLE id_upk_copy nach TABLE_NAME user_id_ufk_copy
Letzteres geschieht über eine Methode meiner Datenbankklasse:
def copy_uuid_from_referenced_table_to_foreign_key_table(self,
referenced_table_name, referenced_table_column_name,
foreign_key_table_name, foreign_key_table_column_name,
from_referenced_table_column_name, to_foreign_key_table_column_name):
# we alias the referenced_table because the key can be in the same table
query = '''
UPDATE {}
INNER JOIN {} abcde
ON abcde.{} = {}.{}
SET {}.{} = abcde.{}'''\
.format(
foreign_key_table_name,
referenced_table_name,
referenced_table_column_name,
foreign_key_table_name, foreign_key_table_column_name,
foreign_key_table_name, to_foreign_key_table_column_name,
from_referenced_table_column_name)
cursor = self.conn.cursor()
self.execute_query(cursor, query)
return True
Das Skript für die Datenbankkonvertierung sieht wie folgt aus:
# convert integer primary keys and integer foreign keys to uuids
def to_uuid():
db = Database(
user=DB_USER,
passwd=DB_PASSWORD,
host=DB_HOST,
db=DB_DATABASE_NAME)
# connect to database
# get all tables
# get all tables with integer primary key id
# create and load new columns: id_ipk_copy, INT(11), and id_upk_copy, CHAR(32)
for table_name in table_names_ipkid:
# create new column id_ipk_copy and copy id column into it
# create new column id_upk_copy and fill with uuids
# create new foreign key uuid columns in tables
for table_name_ipkid in table_names_ipkid:
for row in db.get_all_foreign_keys_to_table(table_name_ipkid, column_name='id'):
foreign_key_table_name = row['FOREIGN_KEY_TABLE_NAME']
foreign_key_table_column_name = row['FOREIGN_KEY_TABLE_COLUMN_NAME']
if not db.table_column_is_integer(foreign_key_table_name, foreign_key_table_column_name):
# already uuid?
continue
referenced_table_name = row['REFERENCED_TABLE_NAME']
referenced_table_column_name = row['REFERENCED_TABLE_COLUMN_NAME']
foreign_key_table_new_column_name = foreign_key_table_column_name + '_ufk_copy'
foreign_key_table_new_column_definition = {
'column_name': foreign_key_table_new_column_name,
'definition': foreign_key_table_new_column_name + ' CHAR(32)',
}
db.table_create_column(foreign_key_table_name, foreign_key_table_new_column_definition)
# copy uuids (id_upk_copy) from referenced_table to new column of foreign_key_table
db.copy_uuid_from_referenced_table_to_foreign_key_table(
referenced_table_name, referenced_table_column_name,
foreign_key_table_name, foreign_key_table_column_name,
'id_upk_copy', foreign_key_table_new_column_name)
# at this point we have:
#
# - tables with an integer primary key column id:
# - have a new column id_ipk_copy with a copy of id
# - have a new column id_upk_copy with uuids values
# - all tables with foreign keys:
# - have an extra foreign key column foreign_key_table_column_name + '_uuid'
#
# now we must rearrange
# first we drop all constraints
...
# 1. Rearrange primary key
# - drop integer primary key column id
# - rename column id_upk_copy to id
...
# 2. Rearrange foreign keys
# for all tables, using column names ending with '_ufk_copy':
# - drop integer foreign key column
# - rename uuid foreign key column to dropped integer foreign key column name
...
# 3. Remove temporary columns
...
# at this point we have:
# a database that has all the data in the correct columns
2. Generieren Sie eine Datenbank DB_FINAL mit Alembic mit UUID Primary Keys und Foreign Keys
Diese Datenbank hat die UUID Primary Keys, UUID Foreign Keys und Beziehungen. Aber sie hat keine Daten. Ich habe einen neuen Baum oder eine neue Version der Software erstellt. Hier nehme ich alle Änderungen vor, um UUID Primary Keys anstelle von Integer Primary Keys zu behandeln. In dieser neuen Version habe ich die folgenden Änderungen an der Datei models.py vorgenommen:
- Ersetzte Integer Primary Keys durch UUID Primary Keys
- Ersetzt Integer Foreign Keys durch UUID Foreign Keys
Der erste Schritt ist die Erstellung einer leeren Datenbank. In mysql habe ich das getan:
drop database peterspython_dev;
create database peterspython_dev;
Als nächstes leeren wir das Verzeichnis alembic/versions. Dann führen wir Alembic aus, um eine neue Version zu erstellen:
alembic revision -m "v2.20 first"
alembic upgrade head
Und tun Sie dies ein zweites Mal, um alle Tabellen und Beziehungen zu generieren:
alembic revision --autogenerate -m "v2.20 2e time"
alembic upgrade head
Ich habe mich noch nicht mit dem Import von GUID() im Prozess Alembic befasst. Bevor ich 'alembic upgrade head' das zweite Mal ausgeführt habe, habe ich die Versionsdatei bearbeitet und die Zeichenfolge ersetzt:
shared.models.GUID()
durch:
sa.CHAR(32)
3. 3. Vergleichen Sie die Datenbanktabellen und Spalten der Datenbank DB_DATA mit den Datenbanktabellen und Spalten der Datenbank DB_FINAL
Dazu habe ich auch ein Skript erstellt. Es ist nicht sehr schwierig, muss aber gemacht werden, unsere Datenbanken müssen identisch sein! Ich vergleiche nicht nur Tabellennamen und Spaltennamen, sondern prüfe auch, ob der DATA_TYPE der Spalten übereinstimmt. Das Vergleichsskript gab mir (Fehler-)Meldungen wie
db1 column content_item_translation.intro data_type text not same as db2 data_type longtext
db1 column content_item_translation.summary data_type text not same as db2 data_type longtext
db1 column mail_smtp_message.body_text data_type text not same as db2 data_type mediumtext
db1 column contact_form.message data_type text not same as db2 data_type mediumtext
Wahrscheinlich habe ich sie von Hand geändert, weil ich gerade mit SQLAlchemy angefangen habe. Ich habe den Datentyp SQLAlchemy Text verwendet und mehr Platz benötigt. Wie auch immer, es wird Zeit, dies richtig zu machen.
Leider ist der einzige Weg, die MySQL Dialekt-Datentypen MEDIUMTEXT und LONGTEXT zu verwenden, was mich einen weiteren Schritt weg von der Unterstützung beider MariaDb / MySQL und PostgreSQL bringt. Aber immerhin sind jetzt beide Datenbanken identisch!
4. Kopieren Sie die Datenbanktabellendaten von DB_DATA in die Datenbanktabellen von DB_FINAL
Natürlich bin ich hier auf ein Problem gestoßen. NULL -Werte der DB_DATA-Datenbank waren keine NULL -Werte in der DB_FINAL-Datenbank. Der Grund dafür war, dass ich ein eigenes Feldtrennzeichen, ein Zeilentrennzeichen, definiert hatte. Als ich im Internet darüber las, schien die Lösung einfach: Verwenden Sie die MariaDb / MySQL -Standardwerte. Dies bedeutet Export durch:
SELECT <column_names_list> FROM <table_name> INTO OUTFILE <outfile_infile>
Und dann durch Importieren:
LOAD DATA LOCAL INFILE <outfile_infile> INTO TABLE <table_name> <column_names_list>
Jetzt werden die NULL -Werte korrekt übertragen. Ein weiteres Problem, auf das Sie stoßen könnten, ist die OUTFILE. Wenn diese Datei existiert, erhalten Sie einen Fehler, also stellen Sie sicher, dass Sie diese Dateien vor einem neuen Lauf entfernen.
Dinge, die schief gelaufen sind
Datenbank hat nicht mehr geantwortet
Vielleicht ist all dieses Hinzufügen und Entfernen von Spalten etwas, das etwas durcheinander bringt. Aber wahrscheinlich war etwas in meinem Code falsch. In der ersten Version habe ich vergessen, die Verbindung zu schließen. Als ich in mysql ging und die Datenbank löschen wollte, bekam ich diese Meldung:
MySQL: Error dropping database (errno 13; errno 17; errno 39)
Das bedeutet, dass es eine oder mehrere Dateien gibt, die vom Datenbankserver gesperrt sind oder was auch immer. Die Lösung ist, in dieses Datenbankverzeichnis auf Ihrem Dateisystem zu gehen und diese Dateien z.B. manuell zu entfernen:
sudo rm /var/lib/mysql/your_database_name/category_translation.ibd
Seien Sie hier vorsichtig! Nachdem ich die Verbindung im Skript geschlossen hatte, sah ich diese Meldung nicht mehr, aber ich dachte, ich gebe sie einfach weiter.
UUID Objekt hat kein Attribut 'übersetzen'.
Beim Testen des Kontaktformulars erhielt ich die Nachricht:
AttributeError: 'UUID' object has no attribute 'translate' when using backend-agnostic GUID type
Warum? Das passierte, als ich zuerst das Objekt mail_message committed habe und dann diese mail_message.id als Foreign Key beim Hinzufügen von Datensätzen zur Tabelle mail_message_to benutzt habe.Nach dem Commit, type(item.id) = <class 'uuid.UUID'>, item.id = dcd0fd6b-cd0f-44b0-92c6-a5f08c0d784f konnte sie nicht in das ForeignKey-Feld geschrieben werden.
Das Problem: Ich hatte die Integer Primary Keys in UUID Primary Keys konvertiert, tat dies aber nicht für die Foreign Keys ... uh oh ... dummes Ich ... Die Lösung war, CHAR(32) in der models.py für GUID() zu ersetzen:
... = Column(CHAR(32), ForeignKey(...
Muß geändert werden in:
... = Column(GUID(), ForeignKey(...
Es war nicht notwendig, Alembic nach dieser Änderung auszuführen.
Fehlende Foreign Keys hinzugefügt
An (mindestens, bisher) drei Stellen habe ich gerade ein Integer zu einer Tabelle hinzugefügt, wo ich ein Foreign Key hätte hinzufügen sollen. Zwei davon waren in ContentItem und ContentItemTranslation klassenlos. Ich habe sie verwendet, um das übergeordnete Element zu markieren. Nachdem ich ein ContentItem oder ContentItemTranslation-Objekt bearbeitet habe, klicke ich auf die Schaltfläche Speichern. Dann wird eine Kopie des aktuellen Datensatzes erstellt, mit einer parent_id des ursprünglichen Datensatzes. Um dies zu beheben, ging ich zur ursprünglichen Datenbank zurück, fügte Foreign Keys hinzu und ließ den Prozess erneut laufen.
Raw SQL
Obwohl ich die meisten SLQAlchemy ORM -Abfragen verwende, verwende ich auch SQLAlchemy Raw SQL. Es stellte sich heraus, dass einige dieser Abfragen fehlschlugen, weil nach der Konvertierung die ids nicht zitiert wurden.
Flask routes
Natürlich gibt es bei vielen Routen ein Problem. In Flask können Sie einen Datentyp für die Parameter der Sichtfunktion angeben, und in den meisten Fällen waren es Integer. Jetzt müssen sie Zeichenketten sein. Beispiel:
@pages_blueprint.route('/category', defaults={'category_id': 0})
@pages_blueprint.route('/category/<int:category_id>')
def category(category_id):
...
Muss geändert werden in:
@pages_blueprint.route('/category', defaults={'category_id': ''})
@pages_blueprint.route('/category/<category_id>')
def category(category_id):
...
Integer Prüfung
An einigen Stellen überprüfe ich explizit, ob ein Wert ein Integer ist. Das bin nur ich im paranoiden Modus. Diese Website verwendet zum Beispiel Flask-Login, und in create_app() haben wir den user_loader:
@login_manager.user_loader
def load_user(user_id):
...
return g.db_session.query(User).get(user_id)
Ich musste die Überprüfung entfernen, ob die user_id wirklich eine Integer ist.
Sortierung
Ja, natürlich habe ich die ID Integer Primary Key in einer Reihe von Fällen zum Sortieren der Datensätze verwendet. Mit UUIDs kommt diese Sortierung durcheinander. Dies wurde durch die Verwendung des (Datensatz) created_on-Zeitstempels behoben. Ich hatte diese Spalte created_on bereits in jeder Tabelle.
WTForms Auswahlfeld
In den meisten Formularen mit Selects verwende ich (id, name) Tupel. Aber die id ist nicht mehr ein Integer. Die Lösung besteht darin, den Parameter coerce=int zu entfernen. Beispiel:
class ContentItemAssignAuthorsForm(FlaskForm):
author_ids = MultiCheckboxField(_('Select authors for content item'), coerce=int)
submit = SubmitField(_l('Assign'))
Muss geändert werden in:
class ContentItemAssignAuthorsForm(FlaskForm):
author_ids = MultiCheckboxField(_('Select authors for content item'))
submit = SubmitField(_l('Assign'))
Zusammenfassung
Dies war das erste Mal, dass ich Python pymysql mit hauptsächlich MariaDb / MySQL Wartungsbefehlen verwendete, wie z.B. Spalteninformationen abrufen, Eingrenzungen, Hinzufügen und Entfernen von Spalten, Speichern und Laden von Daten. Irgendwo während der Konvertierung hatte ich ernsthafte Schwierigkeiten erwartet, aber dies ist nicht eingetreten.
Die Verwendung von UUIDs kann verwirrend sein. Ist es zu einem bestimmten Zeitpunkt ein UUID -Objekt oder eine Zeichenfolge? Ich verwende das Rezept Backend-agnostic GUID Type , siehe Links unten. Ich denke, ich würde es vorziehen, dass UUIDs überall Zeichenketten sind, schließlich brauchen wir das UUID -Objekt nur, wenn wir ein Primary Key oder Foreign Key einfügen.
Links / Impressum
AttributeError: 'UUID' object has no attribute 'replace' when using backend-agnostic GUID type
https://stackoverflow.com/questions/47429929/attributeerror-uuid-object-has-no-attribute-replace-when-using-backend-agno
Backend-agnostic GUID Type
https://docs.sqlalchemy.org/en/13/core/custom_types.html?highlight=guid#backend-agnostic-guid-type
How can I use UUIDs in SQLAlchemy?
https://stackoverflow.com/questions/183042/how-can-i-use-uuids-in-sqlalchemy
How do I see all foreign keys to a table or column?
https://stackoverflow.com/questions/201621/how-do-i-see-all-foreign-keys-to-a-table-or-column
MySQL: Error dropping database (errno 13; errno 17; errno 39)
https://stackoverflow.com/questions/12196996/mysql-error-dropping-database-errno-13-errno-17-errno-39
Replace integer id field with uuid
https://stackoverflow.com/questions/42674931/replace-integer-id-field-with-uuid
SQLAlchemy one to one relationship get parent and add child
https://stackoverflow.com/questions/59227673/sqlalchemy-one-to-one-relationship-get-parent-and-add-child
Using custom UUID Type from SQLAlchemy
https://stackoverflow.com/questions/47275130/using-custom-uuid-type-from-sqlalchemy
What column type does SQLAlchemy use for “Text” on MySQL?
https://stackoverflow.com/questions/47644739/what-column-type-does-sqlalchemy-use-for-text-on-mysql
Neueste
- Ausblenden der Primärschlüssel der Datenbank UUID Ihrer Webanwendung
- Don't Repeat Yourself (DRY) mit Jinja2
- SQLAlchemy, PostgreSQL, maximale Anzahl von Zeilen pro user
- Anzeige der Werte in den dynamischen Filtern SQLAlchemy
- Sichere Datenübertragung mit Public Key Verschlüsselung und pyNaCl
- rqlite: eine hochverfügbare und distverteilte SQLite -Alternative
Meistgesehen
- Verwendung von Pythons pyOpenSSL zur Überprüfung von SSL-Zertifikaten, die von einem Host heruntergeladen wurden
- Verwendung von UUIDs anstelle von Integer Autoincrement Primary Keys mit SQLAlchemy und MariaDb
- Verbindung zu einem Dienst auf einem Docker -Host von einem Docker -Container aus
- PyInstaller und Cython verwenden, um eine ausführbare Python-Datei zu erstellen
- SQLAlchemy: Verwendung von Cascade Deletes zum Löschen verwandter Objekte
- Flask RESTful API Validierung von Anfrageparametern mit Marshmallow-Schemas