So erstellen Sie Django-Modelle

Einführung

Im vorherigen Lernprogramm heißt es: „https://www.digitalocean.com/community/tutorials/how-to-create-a-django-app-and-connect-it-to-a-database[How To Create a Django App and Connect it to a Database] “, befassten wir uns mit dem Erstellen einer MySQL-Datenbank, dem Erstellen und Starten einer Django-Anwendung und dem Herstellen einer Verbindung mit einer MySQL-Datenbank.

In diesem Tutorial erstellen wir die Djangomodels, die die Felder und das Verhalten der Blog-Anwendungsdaten definieren, die wir speichern werden. Diese Modelle ordnen die Daten aus Ihrer Django-Anwendung der Datenbank zu. Django generiert die Datenbanktabellen mithilfe der ORM-API (Object Relational Mapping), die als "Modelle" bezeichnet wird.

Voraussetzungen

Sie sollten MySQL auf einem Ubuntu 16.04-Server installiert haben und eine Datenbankverbindung mit Ihrer Django-Anwendung einrichten. Wenn Sie dies noch nicht getan haben, lesen Sie bitte den zweiten Teil der Django-Reihe „https://www.digitalocean.com/community/tutorials/how-to-create-a-django-app-and-connect-“. it-to-a-database [So erstellen Sie eine Django-App und verbinden sie mit einer Datenbank]. “

[[Schritt-1 - Erstellen einer Django-Anwendung]] == Schritt 1 - Erstellen einer Django-Anwendung

Um der Django-Philosophie der Modularität gerecht zu werden, erstellen wir in unserem Projekt eine Django-App, die alle für die Erstellung der Blog-Website erforderlichen Dateien enthält.

Aktivieren Sie zuerst Ihre virtuelle Python-Umgebung:

cd ~/my_blog_app
. env/bin/activate
cd blog

Führen Sie von dort aus den folgenden Befehl aus:

python manage.py startapp blogsite

Zu diesem Zeitpunkt verfügen Sie über die folgende Verzeichnisstruktur für Ihr Projekt:

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

Die Datei, auf die wir uns in diesem Tutorial konzentrieren, ist diemodels.py-Datei.

[[Schritt-2 - Hinzufügen des Beitragsmodells]] == Schritt 2 - Hinzufügen des Beitragsmodells

Zuerst müssen wir die Dateimodels.pyöffnen und bearbeiten, damit sie den Code zum Generieren einesPost-Modells enthält. Das Modell vonPostenthält die folgenden Datenbankfelder:

  • title - Der Titel des Blogposts.

  • slug - Wo gültige URLs für Webseiten gespeichert und generiert werden.

  • content - Der Textinhalt des Blogposts.

  • created_on - Das Datum, an dem der Beitrag erstellt wurde.

  • author - Die Person, die den Beitrag geschrieben hat.

Ändern Sie nun die Verzeichnisse dahin, wo sich die Dateimodels.pybefindet.

cd ~/my_blog_app/blog/blogsite

Verwenden Sie den Befehlcat, um den Inhalt der Datei in Ihrem Terminal anzuzeigen.

cat models.py

Die Datei sollte den folgenden Code enthalten, der Modelle importiert, sowie einen Kommentar, der beschreibt, was in die Dateimodels.py eingefügt werden soll.

models.py

from django.db import models

# Create your models here.

Fügen Sie mit Ihrem bevorzugten Texteditor oder Ihrer bevorzugten IDE den folgenden Code zur Dateimodels.pyhinzu. Wir verwendennano als Texteditor. Sie können jedoch gerne alles verwenden, was Sie bevorzugen.

nano models.py

In dieser Datei ist der Code zum Importieren der Modell-API bereits hinzugefügt. Sie können den folgenden Kommentar löschen. Dann importieren wirslugify zum Generieren von Slugs aus Strings und DjangosUser zur Authentifizierung wie folgt:

models.py

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

Fügen Sie dann die Klassenmethode zu der Modellklasse hinzu, die wirPost aufrufen möchten, mit den folgenden Datenbankfeldern:title,slug,content,created_on und author.

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()

Als nächstes werden wir Funktionen für die Generierung der URL und die Funktion zum Speichern des Posts hinzufügen. Dies ist von entscheidender Bedeutung, da hierdurch ein eindeutiger Link erstellt wird, der zu unserem eindeutigen Beitrag passt.

models.py

...
@models.permalink
 def get_absolute_url(self):
     return ('blog_post_detail', (),
          {
             'slug': self.slug,
          })
 def save(self, *args, **kwargs):
     if not self.slug:
         self.slug = slugify(self.title)
         super(Post, self).save(*args, **kwargs)

Nun müssen wir dem Modell mitteilen, wie die Beiträge bestellt und auf der Webseite angezeigt werden sollen. Die Logik hierfür wird einer verschachtelten innerenMeta-Klasse hinzugefügt. Die KlasseMetaenthält im Allgemeinen andere wichtige Modelllogiken, die nicht mit der Definition von Datenbankfeldern zusammenhängen.

models.py

...
   class Meta:
        ordering = ['created_on']
        def __unicode__(self):
            return self.title

Schließlich fügen wir dieser Datei das ModellCommenthinzu. Dies beinhaltet das Hinzufügen einer weiteren Klasse mit dem NamenComment mitmodels.Models in der Signatur und den folgenden definierten Datenbankfeldern:

  • name - Der Name der Person, die den Kommentar veröffentlicht.

  • email - Die E-Mail-Adresse der Person, die den Kommentar veröffentlicht.

  • text - Der Text des Kommentars selbst.

  • post - Der Beitrag, mit dem der Kommentar abgegeben wurde.

  • created_on - 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)

Wenn Sie fertig sind, sollte Ihre vollständigemodels.py-Datei folgendermaßen aussehen:

models.py

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


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()

    @models.permalink
    def get_absolute_url(self):
        return ('blog_post_detail', (),
                {
                   'slug': 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)

Stellen Sie sicher, dass Sie die Datei speichern und schließen.

Wenn die Dateimodels.pyeingerichtet ist, können wir die Dateisettings.pyaktualisieren.

[[Schritt-3 -—- Update-Einstellungen]] == Schritt 3 - Update-Einstellungen

Nachdem wir unserer Anwendung Modelle hinzugefügt haben, müssen wir unser Projekt über die Existenz derblogsite-App informieren, die wir gerade hinzugefügt haben. Wir tun dies, indem wir es insettings.py zum AbschnittINSTALLED_APPS hinzufügen.

Navigieren Sie zu dem Verzeichnis, in dem Ihrsettings.pylebt.

cd ~/my_blog_app/blog/blog

Öffnen Sie von hier aus Ihresettings.py-Datei, beispielsweise mit nano, mit dem Befehlnano settings.py.

Fügen Sie bei geöffneter Datei Ihreblogsite-App zum AbschnittINSTALLED_APPS der Datei hinzu, wie unten gezeigt.

settings.py

# Application definition
INSTALLED_APPS = [
    'blogsite',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Mit der hinzugefügten Appblogsitekönnen Sie die Datei speichern und beenden.

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

[[Schritt 4 - Migrationen durchführen]] == Schritt 4 - Migrationen durchführen

Wenn unsere ModellePost undComment hinzugefügt wurden, besteht der nächste Schritt darin, diese Änderungen so anzuwenden, dass unser DatenbankschemaMySQLie erkennt und die erforderlichen Tabellen erstellt.

Werfen wir einen Blick darauf, welche Tabellen bereits in unsererblog_data-Datenbank vorhanden sind.

Dazu müssen wir uns am MySQL-Server anmelden.

[.note] #Note: In diesem Beispiel verwenden wir den Benutzernamenroot ohne Kennwort. Sie sollten jedoch den Benutzernamen und das Kennwort verwenden, die Sie für MySQL eingerichtet haben.
#

mysql blog_data -u root

Sie werden feststellen, dass bei Eingabe des BefehlsSHOW DATABASES;Folgendes angezeigt wird:

Output+--------------------+
| Database           |
+--------------------+
| information_schema |
| blog_data          |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

Wir werden uns dieblog_data-Datenbank ansehen und die bereits vorhandenen Tabellen anzeigen, falls vorhanden.

USE blog_data;

Listen Sie dann die Tabellen auf, die in der Datenbankblog_datavorhanden sind:

SHOW TABLES;
OutputEmpty set (0.00 sec)

Derzeit werden keine Tabellen angezeigt, da wir noch keine Migrationen durchgeführt haben. Wenn wir jedoch Migrationen durchführen, werden die von Django generierten Tabellen angezeigt.

Jetzt werden wir die Migrationen durchführen, die die Änderungen übernehmen, die wir inmodels.py vorgenommen haben.

Schließen Sie MySQL mitCTRL +D.

Zuerst müssen wir unsere Modelländerungen mit dem Befehlmakemigrations in einzelne Migrationsdateien packen. Diese Dateien ähneln denen voncommits in einem Versionskontrollsystem wiegit.

Wenn Sie nun zu~/my_blog_app/blog/blogsite/migrations navigieren undls 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 mitcd in das Blog-Verzeichnis.

cd ~/my_blog_app/blog
python manage.py makemigrations

Sie sollten dann die folgende Ausgabe in Ihrem Terminalfenster sehen:

OutputMigrations for 'blogsite':
  blogsite/migrations/0001_initial.py
    - Create model Comment
    - Create model Post
    - Add field post to comment

Denken Sie daran, als wir zu/~/my_blog_app/blog/blogsite/migrations navigierten und es nur die Datei__init__.py gab? Wenn wir jetztcdin dieses Verzeichnis zurückkehren, werden wir sehen, dass zwei Dinge hinzugefügt wurden,__pycache__ und0001_initial.py. Die Datei0001_initial.py wurde automatisch generiert, wenn Siemakemigrations ausgeführt haben. Eine ähnliche Datei wird jedes Mal generiert, wenn Siemakemigrations ausführen.

Führen Sieless 0001_initial.py aus, wenn Sie sehen möchten, was die Datei enthält.

Navigieren Sie nun zu~/my_blog_app/blog.

Da wir eine Migrationsdatei erstellt haben, müssen wir die Änderungen, die diese Dateien beschreiben, mit dem Befehlmigrate auf die Datenbank anwenden. Lassen Sie uns zunächst mit dem Befehlshowmigrationsehen, welche aktuellen Migrationen vorhanden sind.

python manage.py showmigrations
Outputadmin
 [ ] 0001_initial
 [ ] 0002_logentry_remove_auto_add
auth
 [ ] 0001_initial
 [ ] 0002_alter_permission_name_max_length
 [ ] 0003_alter_user_email_max_length
 [ ] 0004_alter_user_username_opts
 [ ] 0005_alter_user_last_login_null
 [ ] 0006_require_contenttypes_0002
 [ ] 0007_alter_validators_add_error_messages
 [ ] 0008_alter_user_username_max_length
 [ ] 0009_alter_user_last_name_max_length
blogsite
 [ ] 0001_initial
contenttypes
 [ ] 0001_initial
 [ ] 0002_remove_content_type_name
sessions
 [ ] 0001_initial

Sie werden die Migration bemerken, die wir gerade fürblogsite hinzugefügt haben. Diese enthält die Migration0001_initial für die ModellePost undComment.

Sehen wir uns nun die Anweisungen vonSQLan, die ausgeführt werden, sobald wir die Migrationen mit dem folgenden Befehl durchgeführt haben. Es nimmt die Migration und den Titel der Migration als Argument:

python manage.py sqlmigrate blogsite 0001_initial

Wie Sie unten sehen, ist dies die eigentliche SQL-Abfrage, die hinter den Kulissen durchgeführt wird.

BEGIN;
--
-- Create model 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);
--
-- Create model 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);
--
-- Add field post to comment
--
ALTER TABLE `blogsite_comment` ADD COLUMN `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`);
COMMIT;

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

python manage.py migrate

Wir werden die folgende Ausgabe sehen:

OutputOperations to perform:
  Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying blogsite.0001_initial... OK
  Applying sessions.0001_initial... OK

Sie haben Ihre Migrationen nun erfolgreich angewendet.

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

  • Fehlende Unterstützung für Transaktionen im Zusammenhang mit Schemaänderungsvorgängen. Mit anderen Worten, wenn eine Migration nicht erfolgreich angewendet werden kann, müssen Sie die vorgenommenen Änderungen manuell entfernen, um eine weitere Migration zu versuchen. Ein Rollback zu einem früheren Zeitpunkt ist nicht möglich, bevor Änderungen an der fehlgeschlagenen Migration vorgenommen wurden.

  • Bei den meisten Schemaänderungsoperationen schreibt MySQL Tabellen vollständig neu. Im schlimmsten Fall ist die Zeitkomplexität proportional zur Anzahl der Zeilen in der Tabelle, um Spalten hinzuzufügen oder zu entfernen. Laut der Django-Dokumentation kann dies bis zu einer Minute pro Million Zeilen dauern.

  • In MySQL gibt es kleine Grenzen für die Länge von Namen für Spalten, Tabellen und Indizes. Die kombinierte Größe aller Spalten und Indexabdeckungen ist ebenfalls begrenzt. Während einige andere Backends höhere Limits unterstützen können, die in Django erstellt wurden, können dieselben Indizes nicht mit einem MySQL-Backend erstellt werden.

Abwägen Sie für jede Datenbank, die Sie für die Verwendung mit Django in Betracht ziehen, die Vor- und Nachteile der einzelnen Datenbanken.

[[Schritt 5 - Datenbank-Schema überprüfen]] == Schritt 5 - Datenbank-Schema überprüfen

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

Führen Sie dazu den folgenden Befehl im Terminal aus, um sich bei MySQL anzumelden.

mysql blog_data -u root

Zeigen Sie nun die vorhandenen Datenbanken an.

SHOW DATABASES;

Wählen Sie unsere Datenbankblog_data:

USE blog_data;

Geben Sie dann den folgenden Befehl ein, um die Tabellen anzuzeigen.

SHOW TABLES;

Sie sollten Folgendes sehen:

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             |
+----------------------------+

Sie sehenblogsite_comment undblogsite_post. Dies sind die Modelle, die wir selbst hergestellt haben. Vergewissern wir uns, dass sie die von uns definierten Felder enthalten.

DESCRIBE blogsite_comment;
Output+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | 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(11)      | NO   | MUL | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)
DESCRIBE blogsite_post;
Output+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | 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.01 sec)

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

Sie können MySQL mitCTRL +D schließen. Wenn Sie bereit sind, Ihre Python-Umgebung zu verlassen, können Sie den Befehldeactivate ausführen:

deactivate

Wenn Sie Ihre Programmierumgebung deaktivieren, kehren Sie zur Eingabeaufforderung des Terminals zurück.

Fazit

In diesem Tutorial haben wir erfolgreich Modelle für grundlegende Funktionen in einer Blog-Webanwendung hinzugefügt. Sie haben gelernt, wie manmodels codiert, wiemigrations funktioniert und wie man Djangomodels in tatsächlicheMySQLDatenbanktabellen übersetzt.