Required: python 3.11 is already installed.
Choose a directory where the project will be created.
# Create a virtualenv
python3.11 -m venv venv
# Activate venv
source venv/bin/activate
# Update pip
pip install --upgrade pip
# Create a requirements.txt
touch requirements.txt
# copy all librairies into requirements.txt
Django==4.2.8
psycopg2-binary==2.9.9
djangorestframework==3.14.0
django-filter==23.4
dj-rest-auth==5.0.2
drf-spectacular==0.26.5
# Install libraries
pip install -r requirements.txt
django-admin startproject core
Docker engine must be installed, check here: https://docs.docker.com/engine/install/
postgres
docker official imagesdocker pull postgres
Create: core/docker-compose.yml
Default port for postgres is
5432
but I chosse to map to port5433
.
version: "3"
services:
db:
image: postgres:latest
container_name: django-postgres
environment:
POSTGRES_DB: core
POSTGRES_USER: coreuser
POSTGRES_PASSWORD: corepassword
ports:
- "5433:5432"
docker compose up
OR
docker compose up -d
[+] Building 0.0s (0/0) docker:desktop-linux
[+] Running 1/0
✔ Container django-postgres Created 0.0s
Attaching to django-postgres
django-postgres | The files belonging to this database system will be owned by user "postgres".
django-postgres | This user must also own the server process.
django-postgres |
django-postgres | The database cluster will be initialized with locale "en_US.utf8".
django-postgres | The default database encoding has accordingly been set to "UTF8".
django-postgres | The default text search configuration will be set to "english".
django-postgres |
django-postgres | Data page checksums are disabled.
django-postgres |
django-postgres | fixing permissions on existing directory /var/lib/postgresql/data ... ok
django-postgres | creating subdirectories ... ok
django-postgres | selecting dynamic shared memory implementation ... posix
django-postgres | selecting default max_connections ... 100
django-postgres | selecting default shared_buffers ... 128MB
django-postgres | selecting default time zone ... Etc/UTC
django-postgres | creating configuration files ... ok
django-postgres | running bootstrap script ... ok
django-postgres | performing post-bootstrap initialization ... ok
django-postgres | syncing data to disk ... ok
django-postgres |
django-postgres |
django-postgres | Success. You can now start the database server using:
django-postgres |
django-postgres | pg_ctl -D /var/lib/postgresql/data -l logfile start
django-postgres |
django-postgres | initdb: warning: enabling "trust" authentication for local connections
django-postgres | initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.
django-postgres | waiting for server to start....2023-12-04 16:53:23.437 UTC [48] LOG: starting PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
django-postgres | 2023-12-04 16:53:23.438 UTC [48] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
django-postgres | 2023-12-04 16:53:23.440 UTC [51] LOG: database system was shut down at 2023-12-04 16:53:23 UTC
django-postgres | 2023-12-04 16:53:23.442 UTC [48] LOG: database system is ready to accept connections
django-postgres | done
django-postgres | server started
django-postgres | CREATE DATABASE
django-postgres |
django-postgres |
django-postgres | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
django-postgres |
django-postgres | waiting for server to shut down....2023-12-04 16:53:23.589 UTC [48] LOG: received fast shutdown request
django-postgres | 2023-12-04 16:53:23.590 UTC [48] LOG: aborting any active transactions
django-postgres | 2023-12-04 16:53:23.591 UTC [48] LOG: background worker "logical replication launcher" (PID 54) exited with exit code 1
django-postgres | 2023-12-04 16:53:23.591 UTC [49] LOG: shutting down
django-postgres | 2023-12-04 16:53:23.591 UTC [49] LOG: checkpoint starting: shutdown immediate
django-postgres | 2023-12-04 16:53:23.632 UTC [49] LOG: checkpoint complete: wrote 923 buffers (5.6%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.010 s, sync=0.031 s, total=0.042 s; sync files=301, longest=0.008 s, average=0.001 s; distance=4257 kB, estimate=4257 kB; lsn=0/1912FE8, redo lsn=0/1912FE8
django-postgres | 2023-12-04 16:53:23.637 UTC [48] LOG: database system is shut down
django-postgres | done
django-postgres | server stopped
django-postgres |
django-postgres | PostgreSQL init process complete; ready for start up.
django-postgres |
django-postgres | 2023-12-04 16:53:23.707 UTC [1] LOG: starting PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
django-postgres | 2023-12-04 16:53:23.708 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
django-postgres | 2023-12-04 16:53:23.708 UTC [1] LOG: listening on IPv6 address "::", port 5432
django-postgres | 2023-12-04 16:53:23.709 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
django-postgres | 2023-12-04 16:53:23.711 UTC [64] LOG: database system was shut down at 2023-12-04 16:53:23 UTC
django-postgres | 2023-12-04 16:53:23.714 UTC [1] LOG: database system is ready to accept connections
psql -h localhost -p 5433 -d core -U coreuser
Password for user coreuser:
psql (16.1)
Type "help" for help.
core=#
Check postgres version
SELECT version();
core=# SELECT version();
version
---------------------------------------------------------------------------------------------------------------------------
PostgreSQL 16.1 (Debian 16.1-1.pgdg120+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
(1 row)
ALTER ROLE coreuser SET client_encoding TO 'utf8';
ALTER ROLE coreuser SET default_transaction_isolation TO 'read committed';
GRANT ALL PRIVILEGES ON DATABASE core TO coreuser;
core=# ALTER ROLE coreuser SET client_encoding TO 'utf8';
ALTER ROLE
core=# ALTER ROLE coreuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE
core=# GRANT ALL PRIVILEGES ON DATABASE core TO coreuser;
GRANT
settings.py
Replace existing (default) value
Edit: core/core/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'core',
'USER': 'coreuser',
'PASSWORD': 'corepassword',
'HOST': 'localhost',
'PORT': 5433,
}
}
# Migrate database
cd core
python manage.py migrate
> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, authtoken, 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 admin.0003_logentry_add_action_flag_choices... 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 auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying authtoken.0001_initial... OK
Applying authtoken.0002_auto_20160226_1747... OK
Applying authtoken.0003_tokenproxy... OK
Applying sessions.0001_initial... OK
Exemple
username: admin
email: admin@halia.ca
password: admin@1234
python manage.py createsuperuser
> core python manage.py createsuperuser
Username (leave blank to use 'arnaudsene'): admin
Email address: admin@halia.ca
Password:
Password (again):
Superuser created successfully.
Edit: core/core/settings.py
SPECTACULAR_SETTINGS = {
'TITLE': 'Core Project API',
'DESCRIPTION': 'Your project description',
'VERSION': '1.0.0',
# OTHER SETTINGS
}
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # Manually added REST API
'django_filters', # Manually added REST API
'rest_framework.authtoken', # Manually added REST API
'dj_rest_auth', # Manually added REST API
'drf_spectacular', # Manually added for swagger OpenAPI 3.0
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
],
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
}
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / "templates"], # Manually added
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
python manage.py startapp user_management
Create: core/user_management/serializer.py
from django.contrib.auth.models import User, Group
from rest_framework import serializers
class UserSerializer(serializers.HyperlinkedModelSerializer):
"""UserSerializer/"""
class Meta:
"""Meta."""
model = User
fields = ['url', 'username', 'email', 'groups']
class GroupSerializer(serializers.HyperlinkedModelSerializer):
"""GroupSerializer."""
class Meta:
"""Meta."""
model = Group
fields = ['url', 'name']
Edit: core/user_management/views.py
from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
from user_management.serializer import UserSerializer, GroupSerializer
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
permission_classes = [IsAuthenticated]
class GroupViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Group.objects.all()
serializer_class = GroupSerializer
permission_classes = [IsAuthenticated]
Create: core/user_management/urls.py
from rest_framework import routers
from user_management.views import UserViewSet, GroupViewSet
router = routers.DefaultRouter()
router.register(r"users", UserViewSet)
router.register(r"groups", GroupViewSet)
Edit: core/core/urls.py
from django.contrib import admin
from django.urls import path, include
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
from rest_framework import routers
from user_management.urls import router as user_management_router
router = routers.DefaultRouter()
router.registry.extend(user_management_router.registry)
urlpatterns = [
path("schema/", SpectacularAPIView.as_view(), name="schema"),
path(
"swagger/",
SpectacularSwaggerView.as_view(
template_name="swagger-ui.html", url_name="schema"
),
name="swagger-ui",
),
path('api/', include(router.urls), name='api'),
path('admin/', admin.site.urls),
path('auth/', include('dj_rest_auth.urls')),
]
Create: core/templates
Create: core/templates/swagger-ui.html
<!DOCTYPE html>
<html>
<head>
<title>Swagger</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3/swagger-ui.css">
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
<script>
const ui = SwaggerUIBundle({
url: "{% url 'schema' %}",
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
layout: "BaseLayout",
requestInterceptor: (request) => {
request.headers['X-CSRFToken'] = "{{ csrf_token }}"
return request;
}
})
</script>
</body>
</html>
Apply database change
python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, authtoken, contenttypes, sessions
Running migrations:
Applying authtoken.0001_initial... OK
Applying authtoken.0002_auto_20160226_1747... OK
Applying authtoken.0003_tokenproxy... OK
python manage.py runserver
core python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
December 04, 2023 - 17:28:17
Django version 4.2.8, using settings 'core.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Download the schema as YAML file