A co by było, gdybyś mógł zorganizować obiekty bazy danych (np. tabele i widoki) w przestrzenie nazw zgodnie z ich rolami w systemie?
W tym artykule zobaczymy właściwy sposób radzenia sobie ze schematami PostgreSQL w Django i kilka wskazówek na temat Modele Django i Python.
Schemat
Schemat, znany również jako przestrzeń nazw, jest typem obiektu bazy danych, którego celem jest bycie hierarchiczną warstwą organizacyjną znajdującą się tuż pod bazą danych.
W PostgreSQL „public” jest domyślnym schematem, ale możesz utworzyć własny przestrzenie nazw do organizowania innych rodzajów obiektów, takich jak tabele, widoki, funkcje itp.
Hierarchia obiektów bazy danych
- Server |- PostgreSQL Instance (Port 5432 by default) |- Role (Users and Groups) |- Tablespace |- Database |- Trigger |- Extension |- Language |- Schema |- Table |- View |- Materialized View |- Sequence |- Function |- Procedure
O naszym laboratorium
To proste laboratorium z Django w środowisku wirtualnym (z virtualenv) i PostgreSQL zainstalowanym na hoście lokalnym.
- Python 3.8
- Django 3.0
- PostgreSQL 12
Powinien działać z wieloma starszymi wersjami 🙂
Kody
- > SQL (psql);
- $ shell (Linux, FreeBSD, Unix*);
- >>> Powłoka Pythona.
Praktyka
-
PostgreSQL
Struktura bazy danych to pierwsza rzecz, którą zrobimy.
- Utworzenie użytkownika bazy danych dla aplikacji;
- Tworzenie bazy danych;
- Tworzenie schematu;
- Tworzenie tabeli
Stwórzmy własny przykład we wbudowanym narzędziu wiersza poleceń psql:
$ psql
Tworzenie aplikacji użytkownika:
CREATE ROLE user_test ENCRYPTED PASSWORD '123' LOGIN;
Rola bazy danych została utworzona z zaszyfrowanym hasłem i atrybutem logowania (użytkownik).
Tworzenie bazy danych do testów:
> CREATE DATABASE db_test OWNER user_test;
Baza danych jest własnością „user_test”.
Połącz się z nim jako użytkownik „user_test”:
> \c db_test user_test
Wewnątrz powłoki psql \c nazwa użytkownika bazy danych.
Tworzenie schematu:
> CREATE SCHEMA ns_hr;
Przestrzeń nazw dla naszego przykładu jest gotowa!
Pokaż wszystkie schematy, które nie są katalogami:
> SELECT nspname AS namespace FROM pg_catalog.pg_namespace WHERE nspname !~ '(^pg_|information_schema)';
Wyjście:
namespace ----------- public ns_hr
Zwróć uwagę, że pojawia się domyślna przestrzeń nazw (publiczna) i ns_hr, utworzone dla naszego laboratorium.
Tworzenie tabeli w schemacie ns_hr:
> CREATE TABLE ns_hr.tb_person( id_ serial primary key, name text not null, surname text not null );
Prosty stół…
Naciśnij <Ctrl> + D
aby wyjść.
-
Django
Czas na kodowanie w Pythonie!
- Środowisko wirtualne;
- Instalacja modułów Pythona;
- Tworzenie i konfiguracja projektu Django;
- Tworzenie aplikacji Django;
- Tworzenie modelu Django;
- Migracje;
- Testy w powłoce;
Tworzenie środowiska wirtualnego:
$ virtualenv -p `which python3.8` django
Bezwzględna ścieżka pliku binarnego Pythona 3.8 została wskazana jako interpreter Pythona tego środowiska.
Uzyskaj dostęp do katalogu środowiska i aktywuj go:
$ cd django && source bin/activate
Twój znak zachęty uległ zmianie, zaczynał się od „(django)” wskazując, że Twoje środowisko wirtualne zostało aktywowane.
Zainstaluj potrzebne moduły do naszych testów:
$ pip install django psycopg2-binary configobj ipython
Odpowiednio:framework sieciowy Django, sterownik PostgreSQL, czytnik plików konfiguracyjnych i ulepszona powłoka interaktywna.
Tworzenie nowego projektu Django:
$ django-admin startproject my_project
Zmień nazwę katalogu projektu na src:
$ mv my_project src
Ma to na celu ułatwienie hierarchii katalogów i nie wpłynie na wyniki. To dlatego, że ma katalog o tej samej nazwie, co może powodować pewne zamieszanie…
Tworzenie pliku konfiguracji bazy danych:
$ 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
Tutaj stworzyliśmy oddzielny plik konfiguracyjny dla połączenia z bazą danych.
Edytuj główny plik konfiguracyjny projektu:
$ vim src/my_project/settings.py
import os from configobj import ConfigObj
Poniżej importów dodaj linię, która wprowadza klasę ConfigObj.
# 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, } }
Zmodyfikuj „sesję” bazy danych jak powyżej.
Tworzenie linków symbolicznych dla manage.py:
$ ln -s `pwd`/src/manage.py `pwd`/bin/manage.py
Aby ułatwić nam pracę, stworzyliśmy dowiązanie symboliczne do manage.py w katalogu bin, który znajduje się w naszej $PATH.
Uruchom wirtualny serwer WWW:
$ manage.py runserver 0.0.0.0:8000
Przetestuj w przeglądarce:http://localhost:8000, a następnie
Dostęp do katalogu projektu:
$ cd src
Sprawdźmy pliki w bieżącym katalogu:
$ tree .
Wyjście:
. ├── 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
Wyświetlaj zawartość bieżącego katalogu w formacie podobnym do drzewa.
Tutaj widzimy wszystkie pliki wewnątrz projektu.
Pierwsza migracja metadanych Django:
$ manage.py migrate
Utworzenie superużytkownika Django:
$ manage.py createsuperuser
Utwórz aplikację:
$ manage.py startapp human_resource
Edytuj settings.py, aby dodać nową aplikację:
$ 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', ]
Fajna sztuczka Django:możesz użyć katalogu modeli zamiast pliku models.py.
Ale musisz utworzyć plik init dunder (__init__.py) wewnątrz katalogu models.
Zaczynamy!
Tworzenie katalogu modeli w katalogu aplikacji:
$ mkdir human_resource/models
Usuń plik models.py:
$ rm -f human_resource/models.py
Tworzenie modelu:
$ 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'
Aby korzystać z zalet schematów PostgreSQL, wewnątrz twojego modelu, w klasie wewnętrznej Meta, do wartości atrybutu „db_table” musisz umieścić kropkę oddzielającą przestrzeń nazw i obiekt między cudzysłowami.
'schema"."object'
Obiektem może być na przykład tabela lub widok…
Init Dunder w katalogu modeli, aby migracje zaczęły obowiązywać:
vim human_resource/models/__init__.py
from human_resource.models.hr import Person
Jest to konieczne, aby katalog modeli działał jako plik models.py.
(Nie) Migracje:moja baza danych, moje zasady!
Tworzymy strukturę naszej bazy danych i żaden ORM nie powinien tego robić za nas!
Mamy moc!
Mamy potęgę!
Dowodzimy!
Nasza baza danych, nasze zasady!
Po prostu wymodeluj swoją bazę danych własnymi rękami i wykonaj fałszywą migrację Django.
Ponieważ tylko my wiemy, jak należy tworzyć obiekty bazy danych 😉
Dokonaj migracji aplikacji human_resource:
$ manage.py makemigrations human_resource
Fałszywa migracja:
$ manage.py migrate --fake
Sprawdźmy hierarchię katalogów aplikacji:
$ 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)
Wyjście:
Ludwig van Beethoven
>>> p.save() # Persist in database
Naciśnij <Ctrl> + D
wyjść!
Powłoka bazy danych (psql):
$ manage.py dbshell
Zapytanie sprawdzające, czy dane zostały wprowadzone przez Django:
> SELECT id_, name, surname FROM ns_hr.tb_person;
Wyjście:
id | name | surname ----+--------+--------------- 1 | Ludwig | van Beethoven
Wniosek
PostgreSQL to solidny i potężny RDBMS z wieloma funkcjami, w tym przestrzeniami nazw dla swoich obiektów.
Django to świetna platforma internetowa, która jest bardzo solidna i ma również wiele funkcji.
Tak więc możesz wyodrębnij lepsze z obu, aby osiągnąć lepsze wyniki, a jednym ze sposobów jest uzyskanie lepszej organizacji.
Porządkowanie obiektów bazy danych w przestrzeniach nazw zgodnie z ich rolami przyniesie Ci korzyści 😉