PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL Schemas / Namespaces mit Django

Wie wäre es, wenn Sie Ihre Datenbankobjekte (z. B. Tabellen und Ansichten) entsprechend ihrer Rollen im System in Namespaces organisieren könnten?
In diesem Artikel sehen wir den richtigen Umgang mit PostgreSQL-Schemas in Django und einige kleine Tipps dazu Django-Modelle und Python.

Schema

Auch als Namespace bekannt, ist ein Schema ein Typ von Datenbankobjekt, dessen Zweck es ist, eine hierarchische Organisationsebene zu sein, die sich direkt unter einer Datenbank befindet.
Bei PostgreSQL ist „öffentlich“ das Standardschema, aber Sie können Ihr eigenes Schema erstellen Namespaces zum Organisieren von Objekten anderer Art wie Tabellen, Ansichten, Funktionen usw.

Hierarchie der Datenbankobjekte

- Server
   |- PostgreSQL Instance (Port 5432 by default)
       |- Role (Users and Groups)
       |- Tablespace
       |- Database
           |- Trigger
           |- Extension
           |- Language
           |- Schema      
               |- Table
               |- View
               |- Materialized View
               |- Sequence
               |- Function
               |- Procedure

Über unser Labor

Das ist ein einfaches Lab mit Django in einer virtuellen Umgebung (mit virtualenv) und PostgreSQL, das auf localhost installiert ist.

  • Python 3.8
  • Django 3.0
  • PostgreSQL 12

Sollte mit vielen älteren Versionen funktionieren 🙂

Codes

  • > SQL (psql);
  • $-Shell (Linux, FreeBSD, Unix*);
  • >>> Python-Shell.

Üben

  • PostgreSQL

Die Datenbankstruktur ist das erste, was wir tun werden.

  • Erstellen eines Datenbankbenutzers für die Anwendung;
  • Datenbankerstellung;
  • Schemaerstellung;
  • Tabellenerstellung

Lassen Sie uns unser eigenes Beispiel im eingebauten psql-Befehlszeilentool erstellen:

$ psql

Erstellung der Benutzeranwendung:

CREATE ROLE user_test ENCRYPTED PASSWORD '123' LOGIN;

Die Datenbankrolle wurde mit einem verschlüsselten Passwort und Anmeldeattribut (Benutzer) erstellt.

Erstellung einer Datenbank für Tests:

> CREATE DATABASE db_test OWNER user_test;

Die Datenbank gehört „user_test“.

Verbinden Sie sich als Benutzer „user_test“:

> \c db_test user_test

Innerhalb der psql-Shell \c Datenbank-Benutzername.

Erstellung eines Schemas:

> CREATE SCHEMA ns_hr;

Der Namensraum für unser Beispiel ist fertig!

Alle Schemas anzeigen, die keine Kataloge sind:

> SELECT
nspname AS namespace
FROM pg_catalog.pg_namespace
WHERE nspname !~ '(^pg_|information_schema)';

Ausgabe:

namespace 
-----------
 public
 ns_hr

Beachten Sie, dass der Standard-Namespace (öffentlich) und das für unser Lab erstellte ns_hr erscheinen.

Erstellung einer Tabelle im Schema ns_hr:

> CREATE TABLE ns_hr.tb_person(
    id_ serial primary key,
    name text not null,
    surname text not null
);

Eine einfache Tabelle…

Drücken Sie <Ctrl> + D zum Beenden.

  • Django

Es ist Zeit, in Python zu programmieren! 😀

  • Virtuelle Umgebung;
  • Installation von Python-Modulen;
  • Erstellung und Konfiguration von Django-Projekten;
  • Django-App-Erstellung;
  • Django-Modellerstellung;
  • Migrationen;
  • Tests in der Shell;

Erstellung einer virtuellen Umgebung:

$ virtualenv -p `which python3.8` django

Der absolute Pfad der Binärdatei von Python 3.8 wurde als Python-Interpreter dieser Umgebung angegeben.

Greifen Sie auf das Umgebungsverzeichnis zu und aktivieren Sie es:

$ cd django && source bin/activate

Ihre Eingabeaufforderung hat sich geändert, sie begann mit „(django)“, was darauf hinweist, dass Ihre virtuelle Umgebung aktiviert wurde.

Installieren Sie die für unsere Tests erforderlichen Module:

$ pip install django psycopg2-binary configobj ipython

Jeweils:Django-Webframework, PostgreSQL-Treiber, Konfigurationsdatei-Reader und verbesserte interaktive Shell.

Erstellung eines neuen Django-Projekts:

$ django-admin startproject my_project

Benennen Sie das Verzeichnis des Projekts in src:um

$ mv my_project src

Dies dient der Vereinfachung der Verzeichnishierarchie und wirkt sich nicht auf die Ergebnisse aus. Das liegt daran, dass es ein gleichnamiges Verzeichnis hat, das einige Verwirrung stiften kann …

Erstellung der Datenbankkonfigurationsdatei:

$ cat << EOF > src/my_project/db.conf
DB_HOST = 'localhost'
DB_NAME = 'db_test'
DB_USER = 'user_test'
DB_PASSWORD = '123'
DB_PORT = 5432
EOF

Hier haben wir eine separate Konfigurationsdatei für die Datenbankverbindung erstellt.

Bearbeiten Sie die Hauptkonfigurationsdatei des Projekts:

$ vim src/my_project/settings.py

import os

from configobj import ConfigObj

Fügen Sie unter den Imports eine Zeile hinzu, die die Klasse ConfigObj bringt.

# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

# Database configuration file location
DB_CONF_FILE = f'{BASE_DIR}/my_project/db.conf'

# Read the configurations from file
DB_CONFIG = ConfigObj(DB_CONF_FILE)

# Database connection parameters

DB_HOST = DB_CONFIG['DB_HOST']
DB_NAME = DB_CONFIG['DB_NAME']
DB_USER = DB_CONFIG['DB_USER']
DB_PASSWORD = DB_CONFIG['DB_PASSWORD']
DB_PORT = DB_CONFIG['DB_PORT']

DATABASES = {
             'default': {
                         'ENGINE': 'django.db.backends.postgresql',
                         'NAME': DB_NAME,
                         'USER': DB_USER,
                         'PASSWORD': DB_PASSWORD,
                         'HOST': DB_HOST,
                         'PORT': DB_PORT,
                         }
            }

Ändern Sie die „Sitzung“ der Datenbank wie oben beschrieben.

Symbolische Linkerstellung für manage.py:

$ ln -s `pwd`/src/manage.py `pwd`/bin/manage.py

Um unsere Arbeit zu erleichtern, haben wir einen symbolischen Link zu manage.py im bin-Verzeichnis erstellt, das sich in unserem $PATH.

befindet

Virtuellen Webserver ausführen:

$ manage.py runserver 0.0.0.0:8000

Testen Sie in Ihrem Browser:http://localhost:8000 und dann + C zum Abbrechen.

Auf Projektverzeichnis zugreifen:

$ cd src

Überprüfen wir die Dateien im aktuellen Verzeichnis:

$ tree .

Ausgabe:

.
├── manage.py
└── my_project
    ├── db.conf
    ├── __init__.py
    ├── __pycache__
    │   ├── __init__.cpython-38.pyc
    │   ├── settings.cpython-38.pyc
    │   ├── urls.cpython-38.pyc
    │   └── wsgi.cpython-38.pyc
    ├── settings.py
    ├── urls.py
    └── wsgi.py

Listet den Inhalt des aktuellen Verzeichnisses in einem baumähnlichen Format auf.
Hier sehen wir alle Dateien innerhalb des Projekts.

Erste Migration für Django-Metadaten:

$ manage.py migrate

Erstellung eines Superusers von Django:

$ manage.py createsuperuser

App erstellen:

$ manage.py startapp human_resource

Settings.py bearbeiten, um neue App hinzuzufügen:

$ vim my_project/settings.py
# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Custom Apps
    'human_resource',
]

Ein cooler Django-Trick:Sie können statt einer Datei models.py auch ein Verzeichnis models verwenden.
Aber Sie müssen eine Dunder-Init-Datei (__init__.py) im Models-Verzeichnis erstellen.
Los geht's!

Erstellung des Modellverzeichnisses im App-Verzeichnis:

$ mkdir human_resource/models

Entfernen Sie die Datei "models.py":

$ rm -f human_resource/models.py

Modellerstellung:

$ vim human_resource/models/hr.py
from django.db.models import AutoField
from django.db.models import Model
from django.db.models import TextField


class Person(Model):
    '''
    Person Model

    Namespace: ns_hr
    Table: tb_person
    '''

    id_ = AutoField(db_column='id_', name='id', primary_key=True,)
    name = TextField(db_column='name', name='name',)
    surname = TextField(db_column='surname', name='surname',)

    def __str__(self):
        return f'{self.name} {self.surname}'

    class Meta:
        db_table = 'ns_hr"."tb_person'  # 'schema"."object'
        verbose_name_plural = 'Person'

Um die Vorteile von PostgreSQL-Schemas nutzen zu können, müssen Sie innerhalb Ihres Modells in der inneren Klasse Meta zum Wert des Attributs „db_table“ einen Punkt setzen, der Namespace und Objekt zwischen Anführungszeichen trennt.

'schema"."object'

Das Objekt könnte zum Beispiel eine Tabelle oder eine Ansicht sein…

Dunder init im Modellverzeichnis, damit die Migrationen wirksam werden:

vim human_resource/models/__init__.py
from human_resource.models.hr import Person

Dies ist notwendig, damit das Modellverzeichnis als Datei "models.py" funktioniert.

(Keine) Migrationen:Meine Datenbank, meine Regeln!

Wir erstellen die Struktur unserer Datenbank und kein ORM sollte das für uns tun!
Wir haben die Macht!
Wir haben die Macht!
Wir haben das Kommando!

Unsere Datenbank, unsere Regeln! 😉

Modellieren Sie Ihre Datenbank einfach selbst und führen Sie eine gefälschte Django-Migration durch.
Denn nur wir wissen, wie die Datenbankobjekte erstellt werden müssen 😉

Migrationen für die human_resource-App durchführen:

$ manage.py makemigrations human_resource

Gefälschte Migration:

$ manage.py migrate --fake

Überprüfen wir die Verzeichnishierarchie der App:

$ tree human_resource/
human_resource/
├── admin.py
├── apps.py
├── __init__.py
├── migrations
│   ├── 0001_initial.py
│   ├── __init__.py
│   └── __pycache__
│       ├── 0001_initial.cpython-38.pyc
│       └── __init__.cpython-38.pyc
├── models
│   ├── hr.py
│   ├── __init__.py
│   └── __pycache__
│       ├── hr.cpython-38.pyc
│       └── __init__.cpython-38.pyc
├── __pycache__
│   ├── admin.cpython-38.pyc
│   └── __init__.cpython-38.pyc
├── tests.py
└── views.py

Django Shell (Ipython):

$ manage.py shell
>>> from human_resource.models.hr import Person

>>> p = Person(name='Ludwig', surname='van Beethoven')                                                                         

>>> print(p)

Ausgabe:

Ludwig van Beethoven
>>> p.save()   # Persist in database

Drücken Sie <Ctrl> + D zum Beenden!

Datenbank-Shell (psql):

$ manage.py dbshell

Eine Abfrage, um zu prüfen, ob die Daten von Django eingefügt wurden:

>  SELECT id_, name, surname FROM ns_hr.tb_person;

Ausgabe:

 id |  name  |    surname    
----+--------+---------------
  1 | Ludwig | van Beethoven

Schlussfolgerung

PostgreSQL ist ein robustes und leistungsstarkes RDBMS mit vielen Funktionen, einschließlich Namensräumen für seine Objekte.
Django ist ein großartiges Web-Framework, das sehr robust ist und auch viele Funktionen hat.
Sie können es also Extrahieren Sie das Beste aus beiden, um bessere Ergebnisse zu erzielen, und um dies zu erreichen, ist eine der Möglichkeiten, eine bessere Organisation zu erreichen.
Die Organisation Ihrer Datenbankobjekte in Namespaces entsprechend ihren Rollen wird Ihnen Vorteile bringen 😉