4.13. Models Method Classmethod

>>> 
... from django.db import models
... from django.utils.translation import gettext_lazy as _
...
...
... class Customer(BaseModel):
...     firstname = models.CharField(verbose_name=_('Firstname'), max_length=100, null=False, blank=False, default=None)
...     lastname = models.CharField(verbose_name=_('Lastname'), max_length=100, null=False, blank=False, default=None)
...     birthdate = models.DateField(verbose_name=_('Birthdate'), null=True, blank=True, default=None)
...
...     @classmethod
...     def add(cls, firstname, lastname, birthdate):
...         customer = cls(firstname=firstname, lastname=lastname, birthdate=birthdate)
...         customer.full_clean()
...         customer.save()
...         return customer
...
...     def __str__(self):
...         return f'{self.firstname} {self.lastname}'

4.13.1. Use Case - 1

>>> 
... import hashlib
... from uuid import uuid4
... from django.db import models
... from django.http import HttpResponse, HttpRequest
... from django.utils.translation import gettext_lazy as _
...
...
... def get_client_ip(request):
...     x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
...     if x_forwarded_for:
...         ip = x_forwarded_for.split(',')[-1].strip()
...     else:
...         ip = request.META.get('REMOTE_ADDR')
...     return ip
...
...
... def calculate_content_hash(request):
...     if hasattr(request, 'body'):
...         return hashlib.sha1(request.body).hexdigest()
...
...
... class HttpMethod(models.TextChoices):
...     GET = 'GET', _('GET')
...     POST = 'POST', _('POST')
...     PATCH = 'PATCH', _('PATCH')
...     PUT = 'PUT', _('PUT')
...     HEAD = 'HEAD', _('HEAD')
...     DELETE = 'DELETE', _('DELETE')
...     OPTIONS = 'OPTIONS', _('OPTIONS')
...     TRACE = 'TRACE', _('TRACE')
...     CONNECT = 'CONNECT', _('CONNECT')
...
...
... class Stage(models.TextChoices):
...     PRODUCTION = 'production', _('Production')
...     TEST = 'test', _('Test')
...
...
... class Source(models.TextChoices):
...     FRONTEND_APIv1 = 'frontend-api-v1', _('Frontend API v1')
...     FRONTEND_APIv2 = 'frontend-api-v2', _('Frontend API v2')
...     FRONTEND_APIv3 = 'frontend-api-v3', _('Frontend API v3')
...     MOBILE_APIv3 = 'mobile-api-v3', _('Mobile API v3')
...
...
... class HttpLogger(models.Model):
...     added = models.DateTimeField(verbose_name=_('Datetime'), auto_now_add=True)
...     modified = models.DateTimeField(verbose_name=_('Datetime'), auto_now=True, db_index=True)
...     uuid = models.UUIDField(verbose_name=_('Request ID'), null=False, blank=False, default=uuid4, editable=False)
...
...     # Request
...     request_ip = models.GenericIPAddressField(verbose_name=_('Request IP'), null=True, blank=True, default=None)
...     request_method = models.CharField(verbose_name=_('Request Method'), max_length=10, choices=HttpMethod.choices, default=HttpMethod.POST)
...     request_path = models.CharField(verbose_name=_('Request Path'), max_length=255, null=True, blank=True, default=None)
...     request_headers = models.TextField(verbose_name=_('Request Headers'), null=True, blank=True, default=None)
...     request_cookies = models.TextField(verbose_name=_('Request Cookies'), null=True,blank=True, default=None)
...     request_content_type = models.CharField(verbose_name=_('Request Content Type'), max_length=255, null=True, blank=True, default=None)
...     request_content_hash = models.CharField(verbose_name=_('Request Content Hash'), max_length=40, db_index=True, null=True, blank=True, default=None)
...     request_content = models.TextField(verbose_name=_('Request Content'), null=True, blank=True)
...
...     # Response
...     response_status = models.PositiveSmallIntegerField(verbose_name=_('Response Status Code'), null=True, blank=True, default=None)
...     response_reason = models.CharField(verbose_name=_('Response Reason'),max_length=30, null=True, blank=True,default=None)
...     response_headers = models.TextField(verbose_name=_('Response Headers'), null=True,blank=True, default=None)
...     response_cookies = models.TextField(verbose_name=_('Response Cookies'), null=True,blank=True, default=None)
...     response_content_type = models.CharField(verbose_name=_('Response Content Type'), max_length=255, null=True,blank=True, default=None)
...     response_content = models.TextField(verbose_name=_('Response Content'), null=True,blank=True, default=None)
...
...     @classmethod
...     def add(cls, request: HttpRequest, response: HttpResponse):
...         return cls.objects.create(
...             request_ip=get_client_ip(request),
...             request_method=request.method,
...             request_path=request.path,
...             request_headers=request.headers,
...             request_cookies=request.COOKIES,
...             request_content_type=request.content_type,
...             request_content_hash=calculate_content_hash(request),
...             request_content=request.body.decode('utf-8'),
...             response_status=response.status_code,
...             response_reason=response.reason_phrase,
...             response_headers=response.headers,
...             response_cookies=response.cookies,
...             response_content_type=response.headers['Content-Type'],
...             response_content=response.content.decode('utf-8'))
...
...     def __str__(self):
...         return f'[{self.uuid}{self.added}, {self.request_ip}] {self.request_method} {self.request_path}'
...
...     class Meta:
...         verbose_name = _('Http Log')
...         verbose_name_plural = _('Http Logs')