Wie man Django-Modelle erstellt

Einführung

Im vorherigen Tutorial, “ Wie man eine Django-App erstellt und mit einer Datenbank verbindet „, haben wir erklärt, wie man eine MySQL-Datenbank erstellt, wie man eine Django-Anwendung erstellt und startet, und wie man sie mit einer MySQL-Datenbank verbindet.

In diesem Tutorial werden wir die Django-Modelle erstellen, die die Felder und Verhaltensweisen der im Blog-Anwendungsdaten gespeicherten Daten definieren. Diese Modelle ordnen die Daten Ihrer Django-Anwendung der Datenbank zu. Es ist das, was Django verwendet, um die Datenbanktabellen über ihre objektrelationalen Abbildungs (ORM)-API zu generieren, die als „Modelle“ bezeichnet wird.

Voraussetzungen

Dieses Tutorial ist Teil der Django-Entwicklungsreihe und setzt diese fort.

Wenn Sie dieser Reihe nicht gefolgt sind, gehen wir von folgendem aus:

  • Sie haben Django-Version 4 oder höher installiert.
  • Sie haben Ihre Django-App mit einer Datenbank verbunden. Wir verwenden MySQL, und Sie können diese Verbindung herstellen, indem Sie Teil zwei der Django-Serie „Wie man eine Django-App erstellt und mit einer Datenbank verbindet“ befolgen.
  • Sie arbeiten mit einem Unix-basierten Betriebssystem, vorzugsweise einem Ubuntu 22.04-Cloud-Server, da dies das System ist, auf dem wir getestet haben. Wenn Sie Django in einer ähnlichen Umgebung einrichten möchten, verweisen wir auf unser Tutorial „Wie man Django installiert und eine Entwicklungsumgebung auf Ubuntu 22.04 einrichtet“.

Da dieses Tutorial größtenteils mit Django-Modellen umgeht, können Sie möglicherweise auch dann folgen, wenn Sie eine etwas andere Konfiguration haben.

Schritt 1 – Django-Anwendung erstellen

Um der Django-Philosophie der Modularität gerecht zu werden, werden wir eine Django-App innerhalb unseres Projekts erstellen, die alle Dateien enthält, die für die Erstellung der Blog-Website erforderlich sind.

Immer wenn wir in Python und Django arbeiten, sollten wir unsere Python-Virtualenv aktivieren und in das Stammverzeichnis unserer App wechseln. Wenn Sie den Anweisungen in der Serie gefolgt sind, können Sie dies erreichen, indem Sie Folgendes eingeben.

  1. cd ~/my_blog_app
  2. . env/bin/activate
  3. cd blog

Von dort aus führen wir diesen Befehl aus:

  1. python manage.py startapp blogsite

Das wird unsere App zusammen mit einem blogsite Verzeichnis erstellen.

Zu diesem Zeitpunkt in der Tutorial-Reihe haben Sie die folgende Verzeichnisstruktur für Ihr Projekt:

my_blog_app/
└── blog
    ├── blog
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-38.pyc
    │   │   ├── settings.cpython-38.pyc
    │   │   ├── urls.cpython-38.pyc
    │   │   └── wsgi.cpython-38.pyc
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── blogsite
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    └── manage.py

Die Datei, auf die wir uns in diesem Tutorial konzentrieren werden, ist die models.py Datei, die sich im blogsite Verzeichnis befindet.

Schritt 2 — Fügen Sie das Posts-Modell hinzu

Zuerst müssen wir die models.py Datei öffnen und bearbeiten, damit sie den Code zur Erzeugung eines Post Modells enthält. Ein Post Modell enthält die folgenden Datenbankfelder:

  • title — Der Titel des Blogposts.
  • slug — Wo gültige URLs für Webseiten gespeichert und generiert werden.
  • content — Der textuelle Inhalt des Blogposts.
  • created_on — Das Datum, an dem der Beitrag erstellt wurde.
  • author — Die Person, die den Beitrag verfasst hat.

Wechseln Sie nun in das Verzeichnis, in dem sich die models.py Datei befindet.

  1. cd ~/my_blog_app/blog/blogsite

Verwenden Sie das cat Kommando, um den Inhalt der Datei in Ihrem Terminal anzuzeigen.

  1. cat models.py

Die Datei sollte den folgenden Code enthalten, der Modelle importiert, zusammen mit einem Kommentar, der beschreibt, was in diese models.py Datei eingefügt werden soll.

models.py
from django.db import models

# Erstellen Sie hier Ihre Modelle.

Verwenden Sie Ihren bevorzugten Texteditor und fügen Sie den folgenden Code zur Datei models.py hinzu. Wir verwenden nano als Texteditor, aber Sie können gerne Ihren bevorzugten Editor verwenden.

  1. nano models.py

Innerhalb dieser Datei ist bereits der Code zum Importieren der Models-API hinzugefügt. Wir können den anschließenden Kommentar löschen. Dann importieren wir slugify zum Generieren von Slugs aus Strings, Djangos User für die Authentifizierung und reverse aus django.urls, um uns mehr Flexibilität bei der Erstellung von URLs zu geben.

models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse

Als nächstes fügen wir die Klassenmethode auf der Modelklasse hinzu, die wir Post nennen werden, mit den folgenden Datenbankfeldern: title, slug, content, created_on und author. Fügen Sie diese unter Ihre Importanweisungen ein.

models.py
...
class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=255)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    author = models.TextField()

Dann werden wir Funktionalität für die Generierung der URL und die Funktion zum Speichern des Beitrags hinzufügen. Dies ist wichtig, da dies einen eindeutigen Link erstellt, um unseren einzigartigen Beitrag abzustimmen.

models.py
...
    def get_absolute_url(self):
        return reverse('blog_post_detail', args=[self.slug])

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

Jetzt müssen wir dem Modell mitteilen, wie die Beiträge geordnet und auf der Webseite angezeigt werden sollen. Die Logik dafür wird zu einer verschachtelten inneren Meta-Klasse hinzugefügt. Die Meta-Klasse enthält im Allgemeinen andere wichtige Modelllogik, die nicht mit der Definition von Datenbankfeldern zusammenhängt.

models.py
...
    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title

Zum Schluss fügen wir das Comment-Modell zu dieser Datei hinzu. Dies umfasst das Hinzufügen einer weiteren Klasse mit dem Namen Comment, die models.Models in ihrer Signatur enthält, und die folgenden Datenbankfelder definiert:

  • name — Der Name der Person, die den Kommentar veröffentlicht.
  • Email — Die E-Mail-Adresse der Person, die den Kommentar veröffentlicht hat.
  • Text — Der Text des Kommentars selbst.
  • Beitrag — Der Beitrag, zu dem der Kommentar erstellt wurde.
  • Erstellt_am — Die Zeit, zu der der Kommentar erstellt wurde.
models.py
...
class Comment(models.Model):
    name = models.CharField(max_length=42)
    email = models.EmailField(max_length=75)
    website = models.URLField(max_length=200, null=True, blank=True)
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)

An diesem Punkt wird models.py vollständig sein. Stellen Sie sicher, dass Ihre models.py-Datei folgendermaßen aussieht:

models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse


class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=255)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    author = models.TextField()

    def get_absolute_url(self):
        return reverse('blog_post_detail', args=[self.slug])
    
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title


class Comment(models.Model):
    name = models.CharField(max_length=42)
    email = models.EmailField(max_length=75)
    website = models.URLField(max_length=200, null=True, blank=True)
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)


Speichern Sie die Datei und schließen Sie sie. Wenn Sie nano verwenden, können Sie dies tun, indem Sie CTRL und X eingeben, dann Y, dann ENTER.

Mit der eingerichteten models.py-Datei können wir nun unsere settings.py-Datei aktualisieren.

Schritt 3 — Einstellungen aktualisieren

Da wir Modelle zu unserer Anwendung hinzugefügt haben, müssen wir unser Projekt darüber informieren, dass die blogsite-App, die wir gerade hinzugefügt haben, existiert. Dies tun wir, indem wir sie dem Abschnitt INSTALLED_APPS in der settings.py-Datei hinzufügen.

Navigieren Sie zum Verzeichnis, in dem Ihre settings.py-Datei liegt.

  1. cd ~/my_blog_app/blog/blog

Öffnen Sie von hier aus Ihre settings.py-Datei, beispielsweise mit nano.

  1. nano settings.py

Fügen Sie die blogsite-App mit geöffneter Datei dem Abschnitt INSTALLED_APPS der Datei wie unten angegeben hinzu.

settings.py
# Anwendungsdefinition
INSTALLED_APPS = [
    'blogsite',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Mit der blogsite-App hinzugefügt, können Sie die Datei speichern und schließen.

An diesem Punkt sind wir bereit, diese Änderungen anzuwenden.

Schritt 4 – Migrationen erstellen

Mit unseren Modellen Post und Comment hinzugefügt, ist der nächste Schritt, diese Änderungen anzuwenden, damit unser MySQL-Datenbankschema sie erkennt und die notwendigen Tabellen erstellt.

Zuerst müssen wir unsere Modelländerungen in einzelne Migrationsdateien verpacken, indem wir den Befehl makemigrations verwenden. Diese Dateien sind ähnlich wie Commits in einem Versionskontrollsystem wie Git.

Wenn Sie nun zu ~/my_blog_app/blog/blogsite/migrations navigieren und ls ausführen, werden Sie feststellen, dass nur eine __init__.py-Datei vorhanden ist. Dies wird sich ändern, sobald wir die Migrationen hinzufügen.

Wechseln Sie zum Blog-Verzeichnis mit cd, wie folgt:

  1. cd ~/my_blog_app/blog

Dann führen Sie den Befehl makemigrations auf manage.py aus.

  1. python manage.py makemigrations

Sie sollten dann folgende Ausgabe in Ihrem Terminalfenster erhalten:

Output
Migrations for 'blogsite': blogsite/migrations/0001_initial.py - Create model Post - Create model Comment

Erinnern Sie sich, als wir zu /~/my_blog_app/blog/blogsite/migrations navigiert sind und dort nur die Datei __init__.py vorhanden war? Wenn wir jetzt in dieses Verzeichnis zurückkehren (cd), werden wir feststellen, dass zwei Elemente hinzugefügt wurden: __pycache__ und 0001_initial.py. Die Datei 0001_initial.py wurde automatisch generiert, als Sie makemigrations ausgeführt haben. Eine ähnliche Datei wird jedes Mal generiert, wenn Sie makemigrations ausführen.

Führen Sie den Befehl less 0001_initial.py im Verzeichnis aus, wenn Sie den Inhalt der Datei lesen möchten.

Navigieren Sie jetzt zu ~/my_blog_app/blog:

  1. cd ~/my_blog_app/blog

Da wir eine Migrationsdatei erstellt haben, müssen wir die Änderungen, die diese Dateien beschreiben, mit dem Befehl migrate auf die Datenbank anwenden. Aber zuerst schauen wir uns an, welche Migrationen bereits existieren, indem wir den Befehl showmigrations verwenden.

  1. python manage.py showmigrations
Output
admin [X] 0001_initial [X] 0002_logentry_remove_auto_add [X] 0003_logentry_add_action_flag_choices auth [X] 0001_initial [X] 0002_alter_permission_name_max_length [X] 0003_alter_user_email_max_length [X] 0004_alter_user_username_opts [X] 0005_alter_user_last_login_null [X] 0006_require_contenttypes_0002 [X] 0007_alter_validators_add_error_messages [X] 0008_alter_user_username_max_length [X] 0009_alter_user_last_name_max_length [X] 0010_alter_group_name_max_length [X] 0011_update_proxy_permissions blogsite [ ] 0001_initial contenttypes [X] 0001_initial [X] 0002_remove_content_type_name sessions [X] 0001_initial

Sie werden feststellen, dass alle Migrationen überprüft sind, außer derjenigen für 0001_initial, die wir gerade mit den Modellen Post und Comment erstellt haben.

Jetzt schauen wir uns an, welche SQL-Anweisungen ausgeführt werden, wenn wir die Migrationen durchführen, mit dem folgenden Befehl. Er nimmt die Migration und den Titel der Migration als Argument an:

  1. python manage.py sqlmigrate blogsite 0001_initial

Nachfolgend wird die tatsächliche SQL-Abfrage angezeigt, die im Hintergrund ausgeführt wird.

Output
-- -- Erstelle Modell Post -- CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL); -- -- Erstelle Modell Comment -- CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `post_id` integer NOT NULL); ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);

Führen wir nun die Migrationen durch, damit sie auf unsere MySQL-Datenbank angewendet werden.

  1. python manage.py migrate

Wir erhalten die folgende Ausgabe:

Output
Operations to perform: Apply all migrations: admin, auth, blogsite, contenttypes, sessions Running migrations: Applying blogsite.0001_initial... OK

Sie haben Ihre Migrationen erfolgreich angewendet.

Es ist wichtig zu beachten, dass es drei Einschränkungen bei Django-Migrationen mit MySQL als Backend gibt, wie in der Django-Dokumentation angegeben.

  • Fehlende Unterstützung für Transaktionen bei Schema-Änderungsvorgängen. Mit anderen Worten, wenn eine Migration nicht erfolgreich angewendet wird, müssen Sie die Änderungen manuell rückgängig machen, um eine weitere Migration zu versuchen. Es ist nicht möglich, zu einem früheren Zeitpunkt zurückzukehren, bevor Änderungen in der fehlgeschlagenen Migration vorgenommen wurden.
  • Für die meisten Schema-Änderungsvorgänge wird MySQL Tabellen vollständig neu schreiben. Im schlimmsten Fall ist die Zeitkomplexität proportional zur Anzahl der Zeilen in der Tabelle, um Spalten hinzuzufügen oder zu entfernen. Laut Django-Dokumentation könnte dies so langsam sein wie eine Minute pro Million Zeilen.
  • In MySQL gibt es kleine Grenzen für die Namenlängen von Spalten, Tabellen und Indizes. Es gibt auch eine Grenze für die kombinierte Größe aller Spalten und Indexabdeckungen. Während einige andere Backends höhere Grenzen unterstützen können, die in Django erstellt wurden, können dieselben Indizes nicht mit einem MySQL-Backend erstellt werden.

Für jede Datenbank, die Sie für die Verwendung mit Django in Betracht ziehen, sollten Sie die Vor- und Nachteile jeder einzelnen abwägen.

Schritt 5 — Überprüfen des Datenbankschemas

Mit abgeschlossenen Migrationen sollten wir die erfolgreiche Generierung der MySQL-Tabellen überprüfen, die wir über unsere Django-Modelle erstellt haben.

Um dies zu tun, führen Sie den folgenden Befehl im Terminal aus, um sich bei MySQL anzumelden. Wir verwenden den djangouser, den wir im vorherigen Tutorial erstellt haben.

  1. mysql blog_data -u djangouser

Wählen Sie jetzt unsere Datenbank blog_data aus. Wenn Sie nicht wissen, welche Datenbank Sie verwenden, können Sie alle Datenbanken mit SHOW DATABASES; in SQL anzeigen.

  1. USE blog_data;

Dann geben Sie den folgenden Befehl ein, um die Tabellen anzuzeigen.

  1. SHOW TABLES;

Diese SQL-Abfrage sollte Folgendes offenbaren:

Output
+----------------------------+ | Tables_in_blog_data | +----------------------------+ | auth_group | | auth_group_permissions | | auth_permission | | auth_user | | auth_user_groups | | auth_user_user_permissions | | blogsite_comment | | blogsite_post | | django_admin_log | | django_content_type | | django_migrations | | django_session | +----------------------------+ 12 rows in set (0.01 sec)

Zu den Tabellen gehören blogsite_comment und blogsite_post. Dies sind die Modelle, die wir gerade erstellt haben. Überprüfen wir, ob sie die von uns definierten Felder enthalten.

  1. DESCRIBE blogsite_comment;
Output
+------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | name | varchar(42) | NO | | NULL | | | email | varchar(75) | NO | | NULL | | | website | varchar(200) | YES | | NULL | | | content | longtext | NO | | NULL | | | created_on | datetime(6) | NO | | NULL | | | post_id | int | NO | MUL | NULL | | +------------+--------------+------+-----+---------+----------------+ 7 rows in set (0.00 sec)
  1. DESCRIBE blogsite_post;
Output
+------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | title | varchar(255) | NO | | NULL | | | slug | varchar(255) | NO | UNI | NULL | | | content | longtext | NO | | NULL | | | created_on | datetime(6) | NO | | NULL | | | author | longtext | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 6 rows in set (0.00 sec)

Wir haben überprüft, dass die Datenbanktabellen erfolgreich aus unseren Django-Modellmigrationen generiert wurden.

Sie können MySQL mit CTRL + D schließen, und wenn Sie bereit sind, Ihre Python-Umgebung zu verlassen, können Sie den Befehl deactivate ausführen:

  1. deactivate

Wenn Sie Ihre Programmierumgebung deaktivieren, gelangen Sie zurück zur Terminal-Befehlsaufforderung.

Fazit

{
„error“: „Upstream error…“
}

Source:
https://www.digitalocean.com/community/tutorials/how-to-create-django-models