From c015458bb532c4ba8455499077f9dd6266360be0 Mon Sep 17 00:00:00 2001 From: Thuba Mamba Date: Fri, 13 Sep 2024 08:36:06 +0200 Subject: [PATCH] chore: setup DRF in test app, add Booking app for tenants in test app --- django_test_app/bookings/__init__.py | 0 django_test_app/bookings/apps.py | 6 ++ .../bookings/migrations/0001_initial.py | 33 +++++++++++ .../bookings/migrations/__init__.py | 0 django_test_app/bookings/models.py | 16 +++++ django_test_app/bookings/serializers.py | 9 +++ django_test_app/bookings/views.py | 12 ++++ .../companies/migrations/0001_initial.py | 5 +- django_test_app/companies/models.py | 1 - django_test_app/settings.py | 30 ++++++++++ .../users/migrations/0001_initial.py | 1 - django_test_app/users/models.py | 1 - poetry.lock | 58 ++++++++++++++++++- pyproject.toml | 1 + 14 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 django_test_app/bookings/__init__.py create mode 100644 django_test_app/bookings/apps.py create mode 100644 django_test_app/bookings/migrations/0001_initial.py create mode 100644 django_test_app/bookings/migrations/__init__.py create mode 100644 django_test_app/bookings/models.py create mode 100644 django_test_app/bookings/serializers.py create mode 100644 django_test_app/bookings/views.py diff --git a/django_test_app/bookings/__init__.py b/django_test_app/bookings/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/django_test_app/bookings/apps.py b/django_test_app/bookings/apps.py new file mode 100644 index 00000000..ac47a312 --- /dev/null +++ b/django_test_app/bookings/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class BookingsConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "django_test_app.bookings" diff --git a/django_test_app/bookings/migrations/0001_initial.py b/django_test_app/bookings/migrations/0001_initial.py new file mode 100644 index 00000000..498d3f6e --- /dev/null +++ b/django_test_app/bookings/migrations/0001_initial.py @@ -0,0 +1,33 @@ +# Generated by Django 4.2.15 on 2024-09-13 04:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Booking", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("booking_agent_name", models.CharField(max_length=64)), + ("booking_description", models.TextField()), + ("booking_type", models.CharField(max_length=100)), + ("booking_date", models.DateField()), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now=True)), + ], + ), + ] diff --git a/django_test_app/bookings/migrations/__init__.py b/django_test_app/bookings/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/django_test_app/bookings/models.py b/django_test_app/bookings/models.py new file mode 100644 index 00000000..3c07d3f0 --- /dev/null +++ b/django_test_app/bookings/models.py @@ -0,0 +1,16 @@ +from django.db import models + + +# Create your models here. +class Booking(models.Model): + """Test Tenant object.""" + + booking_agent_name = models.CharField(max_length=64) + booking_description = models.TextField() + booking_type = models.CharField(max_length=100) + booking_date = models.DateField() + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.booking_agent_name diff --git a/django_test_app/bookings/serializers.py b/django_test_app/bookings/serializers.py new file mode 100644 index 00000000..12ebc40c --- /dev/null +++ b/django_test_app/bookings/serializers.py @@ -0,0 +1,9 @@ +from rest_framework import serializers + +from django_test_app.bookings.models import Booking + + +class BookingSerializer(serializers.ModelSerializer): + class Meta: + model = Booking + fields = "__all__" diff --git a/django_test_app/bookings/views.py b/django_test_app/bookings/views.py new file mode 100644 index 00000000..52feff19 --- /dev/null +++ b/django_test_app/bookings/views.py @@ -0,0 +1,12 @@ +from rest_framework import viewsets +from rest_framework.permissions import IsAuthenticated + +from django_test_app.bookings.models import Booking +from django_test_app.bookings.serializers import BookingSerializer + + +# Create your views here. +class BookingViewSet(viewsets.ModelViewSet): + queryset = Booking.objects.all() + serializer_class = BookingSerializer + permission_classes = (IsAuthenticated,) diff --git a/django_test_app/companies/migrations/0001_initial.py b/django_test_app/companies/migrations/0001_initial.py index b120d66a..dea95b7f 100644 --- a/django_test_app/companies/migrations/0001_initial.py +++ b/django_test_app/companies/migrations/0001_initial.py @@ -1,6 +1,7 @@ from django.db import migrations, models -from django_tenants.postgresql_backend.base import \ - _check_schema_name as check_schema_name +from django_tenants.postgresql_backend.base import ( + _check_schema_name as check_schema_name, +) class Migration(migrations.Migration): diff --git a/django_test_app/companies/models.py b/django_test_app/companies/models.py index 9e6037e6..c75b4383 100644 --- a/django_test_app/companies/models.py +++ b/django_test_app/companies/models.py @@ -1,6 +1,5 @@ from django.db import models from django_tenants.models import DomainMixin - from tenant_users.tenants.models import TenantBase _NameFieldLength = 64 diff --git a/django_test_app/settings.py b/django_test_app/settings.py index 7d794025..06961fd3 100644 --- a/django_test_app/settings.py +++ b/django_test_app/settings.py @@ -8,7 +8,9 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/3.2/ref/settings/ """ + import os +from datetime import timedelta from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. @@ -39,6 +41,10 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + # DRF apps + "rest_framework", + "rest_framework.authtoken", + "rest_framework_simplejwt", # django-tenant-users apps "tenant_users.permissions", "tenant_users.tenants", @@ -51,6 +57,8 @@ "django.contrib.auth", "django.contrib.contenttypes", "tenant_users.permissions", + # Test project apps - tenant specific apps + "django_test_app.bookings", ] INSTALLED_APPS = list(SHARED_APPS) + [ @@ -67,6 +75,28 @@ TENANT_MODEL = "companies.Company" TENANT_DOMAIN_MODEL = "companies.Domain" +# DRF Configuration +REST_FRAMEWORK = { + "NON_FIELD_ERRORS_KEY": "errors", + "DEFAULT_AUTHENTICATION_CLASSES": [ + "rest_framework_simplejwt.authentication.JWTAuthentication", + ], + "DEFAULT_PERMISSION_CLASSES": [ + "rest_framework.permissions.IsAuthenticated", + ], + "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", + "PAGE_SIZE": 10, +} + +# Simple JWT Configuration +SIMPLE_JWT = { + "AUTH_HEADER_TYPES": ("JWT",), + "ACCESS_TOKEN_LIFETIME": timedelta(days=20), +} + +# Djoser Configuration +# In the event you are using Djoser with DRF for authentication, you easily set it up by following the Djoser documentation - https://djoser.readthedocs.io/en/latest/ + MIDDLEWARE = [ "django_tenants.middleware.main.TenantMainMiddleware", diff --git a/django_test_app/users/migrations/0001_initial.py b/django_test_app/users/migrations/0001_initial.py index e4094b0f..2b3566a9 100644 --- a/django_test_app/users/migrations/0001_initial.py +++ b/django_test_app/users/migrations/0001_initial.py @@ -1,5 +1,4 @@ from django.db import migrations, models - from tenant_users.permissions.models import PermissionsMixinFacade diff --git a/django_test_app/users/models.py b/django_test_app/users/models.py index 63ee365d..3799ebe5 100644 --- a/django_test_app/users/models.py +++ b/django_test_app/users/models.py @@ -1,5 +1,4 @@ from django.db import models - from tenant_users.tenants.models import UserProfile _NameFieldLength = 64 diff --git a/poetry.lock b/poetry.lock index b6f856f7..49be1599 100644 --- a/poetry.lock +++ b/poetry.lock @@ -610,6 +610,45 @@ files = [ [package.dependencies] Django = ">=2.1,<5.2" +[[package]] +name = "djangorestframework" +version = "3.15.2" +description = "Web APIs for Django, made easy." +optional = false +python-versions = ">=3.8" +files = [ + {file = "djangorestframework-3.15.2-py3-none-any.whl", hash = "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20"}, + {file = "djangorestframework-3.15.2.tar.gz", hash = "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad"}, +] + +[package.dependencies] +"backports.zoneinfo" = {version = "*", markers = "python_version < \"3.9\""} +django = ">=4.2" + +[[package]] +name = "djangorestframework-simplejwt" +version = "5.3.1" +description = "A minimal JSON Web Token authentication plugin for Django REST Framework" +optional = false +python-versions = ">=3.8" +files = [ + {file = "djangorestframework_simplejwt-5.3.1-py3-none-any.whl", hash = "sha256:381bc966aa46913905629d472cd72ad45faa265509764e20ffd440164c88d220"}, + {file = "djangorestframework_simplejwt-5.3.1.tar.gz", hash = "sha256:6c4bd37537440bc439564ebf7d6085e74c5411485197073f508ebdfa34bc9fae"}, +] + +[package.dependencies] +django = ">=3.2" +djangorestframework = ">=3.12" +pyjwt = ">=1.7.1,<3" + +[package.extras] +crypto = ["cryptography (>=3.3.1)"] +dev = ["Sphinx (>=1.6.5,<2)", "cryptography", "flake8", "freezegun", "ipython", "isort", "pep8", "pytest", "pytest-cov", "pytest-django", "pytest-watch", "pytest-xdist", "python-jose (==3.3.0)", "sphinx_rtd_theme (>=0.1.9)", "tox", "twine", "wheel"] +doc = ["Sphinx (>=1.6.5,<2)", "sphinx_rtd_theme (>=0.1.9)"] +lint = ["flake8", "isort", "pep8"] +python-jose = ["python-jose (==3.3.0)"] +test = ["cryptography", "freezegun", "pytest", "pytest-cov", "pytest-django", "pytest-xdist", "tox"] + [[package]] name = "doc8" version = "1.1.2" @@ -1496,6 +1535,23 @@ files = [ [package.extras] plugins = ["importlib-metadata"] +[[package]] +name = "pyjwt" +version = "2.9.0" +description = "JSON Web Token implementation in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, + {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, +] + +[package.extras] +crypto = ["cryptography (>=3.4.0)"] +dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] +docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] + [[package]] name = "pytest" version = "8.3.2" @@ -2327,4 +2383,4 @@ test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-it [metadata] lock-version = "2.0" python-versions = "^3.8.1" -content-hash = "dffeebfc1953c44bf9dfa14faa9818bd839b6326a32a9bf67c5d7d3c64edabba" +content-hash = "1b4e636cebb9296c0ceb3538dda88e2f4608fe49970944d41a8354b744e02947" diff --git a/pyproject.toml b/pyproject.toml index 793fef51..86323063 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,7 @@ classifiers = [ python = "^3.8.1" Django = ">=4.2" django-tenants = "^3.6" +djangorestframework-simplejwt = "^5.3.1" [tool.poetry.group.test.dependencies]