sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL-schema's / naamruimten met Django

Wat als u uw database-objecten (bijv. tabellen en views) zou kunnen organiseren in naamruimten volgens de rollen in het systeem?
In dit artikel zullen we de juiste manier zien om met PostgreSQL-schema's in Django om te gaan en enkele kleine tips over Django-modellen en Python.

Schema

Schema, ook bekend als een naamruimte, is een type databaseobject waarvan het doel is om een ​​hiërarchische organisatielaag te zijn die zich net onder een database bevindt.
Op PostgreSQL is "public" het standaardschema, maar u kunt uw eigen schema maken naamruimten om andere soorten objecten te ordenen, zoals tabellen, weergaven, functies en dergelijke.

Hiërarchie databaseobjecten

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

Over ons Lab

Dat is een eenvoudig lab met Django in een virtuele omgeving (met virtualenv) en PostgreSQL geïnstalleerd in localhost.

  • Python 3.8
  • Django 3.0
  • PostgreSQL 12

Zou met veel oudere versies moeten werken 🙂

Codes

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

Oefen

  • PostgreSQL

De databasestructuur is het eerste dat we gaan doen.

  • Aanmaken van databasegebruiker voor de applicatie;
  • Database maken;
  • Schema maken;
  • Tafel maken

Laten we ons eigen voorbeeld maken in de ingebouwde opdrachtregeltool van psql:

$ psql

Creëren van gebruikerstoepassing:

CREATE ROLE user_test ENCRYPTED PASSWORD '123' LOGIN;

De databaserol is gemaakt met een versleuteld wachtwoord en login-attribuut (gebruiker).

Creëren van database voor tests:

> CREATE DATABASE db_test OWNER user_test;

De database is eigendom van "user_test".

Verbind ermee als gebruiker "user_test":

> \c db_test user_test

Binnen de psql shell \c database gebruikersnaam.

Een schema maken:

> CREATE SCHEMA ns_hr;

De naamruimte voor ons voorbeeld is klaar!

Alle schema's weergeven die geen catalogi zijn:

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

Uitgang:

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

Merk op dat de standaard naamruimte (openbaar) en de ns_hr verschijnen, gemaakt voor ons lab.

Een tabel maken in het ns_hr-schema:

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

Een simpele tafel…

Druk op <Ctrl> + D om af te sluiten.

  • Django

Het is tijd om te coderen in Python!

  • Virtuele omgeving;
  • Installatie van Python-modules;
  • Django-project maken en configureren;
  • Django-app maken;
  • Django-model maken;
  • Migraties;
  • Testen in shell;

Virtuele omgeving maken:

$ virtualenv -p `which python3.8` django

Het absolute pad van binair van Python 3.8 werd aangegeven als Python-interpreter van deze omgeving.

Open de directory van de omgeving en activeer deze:

$ cd django && source bin/activate

Uw prompt is gewijzigd, begon bij "(django)" om aan te geven dat uw virtuele omgeving is geactiveerd.

Installeer benodigde modules voor onze tests:

$ pip install django psycopg2-binary configobj ipython

Respectivaly:Django-webframework, PostgreSQL-stuurprogramma, configuratiebestandlezer en verbeterde interactieve shell.

Nieuw Django-project maken:

$ django-admin startproject my_project

Hernoem de map van het project naar src:

$ mv my_project src

Dit is voor het gemak van de directoryhiërarchie en heeft geen invloed op de resultaten. Het is omdat dat een map met dezelfde naam heeft die enige verwarring kan veroorzaken...

Maken van databaseconfiguratiebestand:

$ 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 hebben we een apart configuratiebestand gemaakt voor de databaseverbinding.

Bewerk het hoofdconfiguratiebestand van het project:

$ vim src/my_project/settings.py

import os

from configobj import ConfigObj

Voeg onder de imports een regel toe die de ConfigObj-klasse brengt.

# 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,
                         }
            }

Wijzig de database "sessie" zoals hierboven.

Symbolische koppeling maken voor manage.py:

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

Om ons werk te vergemakkelijken, hebben we een symbolische link naar manage.py gemaakt in de bin-directory die zich in ons $PATH bevindt.

Voer virtuele webserver uit:

$ manage.py runserver 0.0.0.0:8000

Test in uw browser:http://localhost:8000 en dan + C om af te breken.

Toegang tot projectdirectory:

$ cd src

Laten we de bestanden in de huidige map controleren:

$ tree .

Uitgang:

.
├── 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

Maak een lijst van de inhoud van de huidige map in een boomstructuur.
Hier zien we alle bestanden in het project.

Eerste migratie voor Django-metadata:

$ manage.py migrate

Aanmaak van supergebruiker van Django:

$ manage.py createsuperuser

Maak een app:

$ manage.py startapp human_resource

Bewerk settings.py om nieuwe app toe te voegen:

$ 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',
]

Een coole Django-truc:je kunt een directory models gebruiken in plaats van een bestand models.py.
Maar je moet een dunder-init-bestand (__init__.py) maken in de modellendirectory.
Laten we gaan!

Maken van een modellenmap in de app-map:

$ mkdir human_resource/models

Verwijder het bestand models.py:

$ rm -f human_resource/models.py

Model maken:

$ 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'

Om te profiteren van de voordelen van PostgreSQL-schema's, moet u binnen uw model, in Meta inner class, voor de waarde van het kenmerk "db_table" een punt plaatsen die de naamruimte en het object scheidt tussen aanhalingstekens.

'schema"."object'

Het object kan bijvoorbeeld een tafel of een weergave zijn...

Dunder init in de modellenmap om de migraties van kracht te laten worden:

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

Dit is nodig om ervoor te zorgen dat de map modellen werkt als het bestand models.py.

(Nee) Migraties:mijn database, mijn regels!

We creëren de structuur van onze database en geen enkele ORM zou het voor ons moeten doen!
Wij hebben de macht!
We hebben de macht!
Wij hebben de leiding!

Onze database, onze regels!

Modelleer gewoon je database met je eigen handen en maak een nep-Django-migratie.
Omdat alleen wij weten hoe de database-objecten moeten worden gemaakt 😉

Maak migraties voor human_resource-app:

$ manage.py makemigrations human_resource

Nepmigratie:

$ manage.py migrate --fake

Laten we de directoryhiërarchie van de app controleren:

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

Uitgang:

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

Druk op <Ctrl> + D om af te sluiten!

Databaseshell (psql):

$ manage.py dbshell

Een vraag om te controleren of de gegevens zijn ingevoegd door Django:

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

Uitgang:

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

Conclusie

PostgreSQL is een robuust en krachtig RDBMS met veel functies, waaronder naamruimten voor zijn objecten.
Django is een geweldig webframework dat zeer robuust is en ook veel functies heeft.
Dus u kunt haal het beste van beide eruit om betere resultaten te behalen en om dit te doen, is een van de manieren om een ​​betere organisatie te krijgen.
Het organiseren van uw database-objecten in naamruimten volgens hun rollen zal voordelen voor u opleveren 😉


  1. hoe tekenreeksen in verschillende kolommen te scheiden?

  2. Hoe u de dag van een datum haalt in T-SQL

  3. MySQL-query om kolomnamen te krijgen?

  4. Aantal SQL(*) prestaties