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