feat: Add field Meta.sub_model_type to sub-models

ref: #732 #564
This commit is contained in:
2025-04-26 06:00:34 +09:30
parent dbc849d3f1
commit b6146b7d14
19 changed files with 83 additions and 13 deletions

View File

@ -15,6 +15,8 @@ class Contact(
'email', 'email',
] ]
sub_model_type = 'contact'
verbose_name = 'Contact' verbose_name = 'Contact'
verbose_name_plural = 'Contacts' verbose_name_plural = 'Contacts'

View File

@ -22,6 +22,8 @@ class Entity(
'organization', 'organization',
] ]
sub_model_type = 'entity'
verbose_name = 'Entity' verbose_name = 'Entity'
verbose_name_plural = 'Entities' verbose_name_plural = 'Entities'

View File

@ -20,6 +20,8 @@ class Person(
'dob', 'dob',
] ]
sub_model_type = 'person'
verbose_name = 'Person' verbose_name = 'Person'
verbose_name_plural = 'People' verbose_name_plural = 'People'

View File

@ -2,7 +2,7 @@ from drf_spectacular.utils import extend_schema_serializer
from access.models.contact import Contact from access.models.contact import Contact
from access.serializers.person import ( from access.serializers.entity_person import (
BaseSerializer as BaseBaseSerializer, BaseSerializer as BaseBaseSerializer,
ModelSerializer as BaseModelSerializer, ModelSerializer as BaseModelSerializer,
) )

View File

@ -31,10 +31,16 @@ def spectacular_request_serializers( serializer_type = 'Model'):
if issubclass(model, Entity): if issubclass(model, Entity):
serializer_name = 'entity'
if model != Entity:
serializer_name += '_' + model._meta.sub_model_type
serializer_module = importlib.import_module( serializer_module = importlib.import_module(
model._meta.app_label + '.serializers.' + str( model._meta.app_label + '.serializers.' + str(
model._meta.verbose_name serializer_name
).lower().replace(' ', '_') )
) )
serializers.update({ serializers.update({

View File

@ -790,7 +790,7 @@ class SubModelViewSet(
for related_object in model._meta.related_objects: for related_object in model._meta.related_objects:
if( if(
related_object.related_model._meta.verbose_name == self.base_model._meta.verbose_name getattr(related_object.related_model._meta,'sub_model_type', '' ) == self.base_model._meta.sub_model_type
or not issubclass(related_object.related_model, self.base_model) or not issubclass(related_object.related_model, self.base_model)
): ):
@ -801,7 +801,7 @@ class SubModelViewSet(
if( if(
str( str(
related_object.related_model._meta.verbose_name related_object.related_model._meta.sub_model_type
).lower().replace(' ', '_') == model_kwarg ).lower().replace(' ', '_') == model_kwarg
): ):
@ -819,10 +819,17 @@ class SubModelViewSet(
def get_serializer_class(self): def get_serializer_class(self):
serializer_name = self.base_model._meta.verbose_name.lower().replace(' ', '_')
if self.base_model != self.model:
serializer_name += '_' + self.model._meta.sub_model_type
serializer_module = importlib.import_module( serializer_module = importlib.import_module(
self.model._meta.app_label + '.serializers.' + str( self.model._meta.app_label + '.serializers.' + str(
self.model._meta.verbose_name serializer_name
).lower().replace(' ', '_') )
) )
if ( if (

View File

@ -16,6 +16,11 @@ import sys
from pathlib import Path from pathlib import Path
from split_settings.tools import optional, include from split_settings.tools import optional, include
import django.db.models.options as options
options.DEFAULT_NAMES = (*options.DEFAULT_NAMES, 'sub_model_type')
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent

View File

@ -110,6 +110,8 @@ class TicketBase(
unique_together = ('external_system', 'external_ref',) unique_together = ('external_system', 'external_ref',)
sub_model_type = 'ticket'
verbose_name = "Ticket" verbose_name = "Ticket"
verbose_name_plural = "Tickets" verbose_name_plural = "Tickets"

View File

@ -29,6 +29,8 @@ class TicketCommentBase(
unique_together = ('external_system', 'external_ref',) unique_together = ('external_system', 'external_ref',)
sub_model_type = 'comment'
verbose_name = "Ticket Comment" verbose_name = "Ticket Comment"
verbose_name_plural = "Ticket Comments" verbose_name_plural = "Ticket Comments"

View File

@ -13,9 +13,11 @@ class TicketCommentSolution(
'id' 'id'
] ]
verbose_name = "Solution" sub_model_type = 'solution'
verbose_name_plural = "Solutions" verbose_name = "Ticket Comment Solution"
verbose_name_plural = "Ticket Comment Solutions"
def clean(self): def clean(self):

View File

@ -27,10 +27,16 @@ def spectacular_request_serializers( serializer_type = 'Model'):
if issubclass(model, TicketBase): if issubclass(model, TicketBase):
serializer_name = 'ticket'
if model._meta.model_name != 'ticketbase':
serializer_name += '_' + model._meta.sub_model_type
serializer_module = importlib.import_module( serializer_module = importlib.import_module(
model._meta.app_label + '.serializers.' + str( model._meta.app_label + '.serializers.' + str(
model._meta.verbose_name serializer_name
).lower().replace(' ', '_') )
) )
serializers.update({ serializers.update({

View File

@ -15,6 +15,8 @@ class Employee(
'email', 'email',
] ]
sub_model_type = 'employee'
verbose_name = 'Employee' verbose_name = 'Employee'
verbose_name_plural = 'Employees' verbose_name_plural = 'Employees'

View File

@ -1,6 +1,6 @@
from drf_spectacular.utils import extend_schema_serializer from drf_spectacular.utils import extend_schema_serializer
from access.serializers.contact import ( from access.serializers.entity_contact import (
BaseSerializer as ContactBaseSerializer, BaseSerializer as ContactBaseSerializer,
ModelSerializer as ContactModelSerializer, ModelSerializer as ContactModelSerializer,
) )

View File

@ -19,6 +19,8 @@ class RequestTicket(
('triage_requestticket', 'Can triage request ticket'), ('triage_requestticket', 'Can triage request ticket'),
] ]
sub_model_type = 'request'
verbose_name = 'Request' verbose_name = 'Request'
verbose_name_plural = 'Requests' verbose_name_plural = 'Requests'

View File

@ -19,6 +19,8 @@ class SLMTicket(
'id', 'id',
] ]
sub_model_type = 'slm'
verbose_name = 'SLM Ticket Base' verbose_name = 'SLM Ticket Base'
verbose_name_plural = 'SLM Tickets' verbose_name_plural = 'SLM Tickets'

View File

@ -1,6 +1,6 @@
from drf_spectacular.utils import extend_schema_serializer from drf_spectacular.utils import extend_schema_serializer
from itim.serializers.slm_ticket_base import ( from itim.serializers.ticket_slm import (
BaseSerializer as SLMTicketBaseSerializer, BaseSerializer as SLMTicketBaseSerializer,
ModelSerializer as SLMTicketModelSerializer, ModelSerializer as SLMTicketModelSerializer,
ViewSerializer as SLMTicketViewSerializer ViewSerializer as SLMTicketViewSerializer

View File

@ -59,6 +59,34 @@ All models must meet the following requirements:
- Models must save audit history - Models must save audit history
## Creating a Model
Within Centurion ERP there are two types of models, they are:
- Standard
- Sub-Model
### Standard Model
This is your typical model that you would define within any Django Application. This includes Abstract models and precludes multi-table inherited models.
### Sub-Model
This model is known within Django as multi-table inherited models. That is where the base model is a concrete class (not an Abstract model) and the super model inherits from the concrete base model. In this instance both models get their own database tables.
#### Requirements
- Must **not** be an abstract class
- Attribute `sub_model_type` must be specified within the models `Meta` sub-class
- File name is `<base model>_<sub_model_type>` where `base model` is the value of `Meta.sub_model_type` or the first model in the chain.
## Checklist ## Checklist
This section details the additional items that may need to be done when adding a new model: This section details the additional items that may need to be done when adding a new model: