-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into reset_password
- Loading branch information
Showing
20 changed files
with
906 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{{! Based off of: https://github.com/NilsJPWerner/autoDocstring/blob/master/src/docstring/templates/google-notypes.mustache }} | ||
{{summaryPlaceholder}} | ||
|
||
{{extendedSummaryPlaceholder}} | ||
{{#parametersExist}} | ||
|
||
Args: | ||
{{#args}} | ||
{{var}}: {{descriptionPlaceholder}} | ||
{{/args}} | ||
{{#kwargs}} | ||
{{var}}: {{descriptionPlaceholder}} | ||
{{/kwargs}} | ||
{{/parametersExist}} | ||
{{#exceptionsExist}} | ||
|
||
Raises: | ||
{{#exceptions}} | ||
{{type}}: {{descriptionPlaceholder}} | ||
{{/exceptions}} | ||
{{/exceptionsExist}} | ||
{{#returnsExist}} | ||
|
||
Returns: | ||
{{#returns}} | ||
{{descriptionPlaceholder}} | ||
{{/returns}} | ||
{{/returnsExist}} | ||
{{#yieldsExist}} | ||
|
||
Yields: | ||
{{#yields}} | ||
{{descriptionPlaceholder}} | ||
{{/yields}} | ||
{{/yieldsExist}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ | |
""" | ||
|
||
from .base import * | ||
from .model import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,41 @@ | ||
""" | ||
© Ocado Group | ||
Created on 20/01/2024 at 11:19:24(+00:00). | ||
Created on 29/01/2024 at 14:27:09(+00:00). | ||
Base model serializers. | ||
Base serializer. | ||
""" | ||
|
||
import typing as t | ||
|
||
from django.db.models import Model | ||
from rest_framework.serializers import ModelSerializer as _ModelSerializer | ||
from django.contrib.auth.models import AnonymousUser | ||
from rest_framework.serializers import BaseSerializer as _BaseSerializer | ||
|
||
AnyModel = t.TypeVar("AnyModel", bound=Model) | ||
from ..request import Request | ||
from ..user.models import User | ||
|
||
|
||
class ModelSerializer(_ModelSerializer[AnyModel], t.Generic[AnyModel]): | ||
"""Base model serializer for all model serializers.""" | ||
# pylint: disable-next=abstract-method | ||
class BaseSerializer(_BaseSerializer): | ||
"""Base serializer to be inherited by all other serializers.""" | ||
|
||
# pylint: disable-next=useless-parent-delegation | ||
def update(self, instance, validated_data: t.Dict[str, t.Any]): | ||
return super().update(instance, validated_data) | ||
@property | ||
def request(self): | ||
"""The HTTP request that triggered the view.""" | ||
|
||
# pylint: disable-next=useless-parent-delegation | ||
def create(self, validated_data: t.Dict[str, t.Any]): | ||
return super().create(validated_data) | ||
return t.cast(Request, self.context["request"]) | ||
|
||
@property | ||
def request_user(self): | ||
""" | ||
The user that made the request. Assumes the user has authenticated. | ||
""" | ||
|
||
return t.cast(User, self.request.user) | ||
|
||
@property | ||
def request_anon_user(self): | ||
""" | ||
The user that made the request. Assumes the user has not authenticated. | ||
""" | ||
|
||
return t.cast(AnonymousUser, self.request.user) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
""" | ||
© Ocado Group | ||
Created on 20/01/2024 at 11:19:24(+00:00). | ||
Base model serializers. | ||
""" | ||
|
||
import typing as t | ||
|
||
from django.db.models import Model | ||
from rest_framework.serializers import ListSerializer as _ListSerializer | ||
from rest_framework.serializers import ModelSerializer as _ModelSerializer | ||
from rest_framework.serializers import ValidationError as _ValidationError | ||
|
||
from .base import BaseSerializer | ||
|
||
AnyModel = t.TypeVar("AnyModel", bound=Model) | ||
|
||
|
||
class ModelSerializer( | ||
BaseSerializer, | ||
_ModelSerializer[AnyModel], | ||
t.Generic[AnyModel], | ||
): | ||
"""Base model serializer for all model serializers.""" | ||
|
||
# pylint: disable-next=useless-parent-delegation | ||
def update(self, instance, validated_data: t.Dict[str, t.Any]): | ||
return super().update(instance, validated_data) | ||
|
||
# pylint: disable-next=useless-parent-delegation | ||
def create(self, validated_data: t.Dict[str, t.Any]): | ||
return super().create(validated_data) | ||
|
||
def validate(self, attrs: t.Dict[str, t.Any]): | ||
return attrs | ||
|
||
|
||
class ModelListSerializer( | ||
BaseSerializer, | ||
t.Generic[AnyModel], | ||
_ListSerializer[t.List[AnyModel]], | ||
): | ||
"""Base model list serializer for all model list serializers. | ||
Inherit this class if you wish to custom handle bulk create and/or update. | ||
class UserListSerializer(ModelListSerializer[User]): | ||
def create(self, validated_data): | ||
... | ||
def update(self, instance, validated_data): | ||
... | ||
class UserSerializer(ModelSerializer[User]): | ||
class Meta: | ||
model = User | ||
list_serializer_class = UserListSerializer | ||
""" | ||
|
||
instance: t.List[AnyModel] | ||
batch_size: t.Optional[int] = None | ||
|
||
@classmethod | ||
def get_model_class(cls) -> t.Type[AnyModel]: | ||
"""Get the model view set's class. | ||
Returns: | ||
The model view set's class. | ||
""" | ||
|
||
# pylint: disable-next=no-member | ||
return t.get_args(cls.__orig_bases__[0])[ # type: ignore[attr-defined] | ||
0 | ||
] | ||
|
||
def create(self, validated_data: t.List[t.Dict[str, t.Any]]): | ||
"""Bulk create many instances of a model. | ||
https://www.django-rest-framework.org/api-guide/serializers/#customizing-multiple-create | ||
Args: | ||
validated_data: The data used to create the models. | ||
Returns: | ||
The models. | ||
""" | ||
|
||
model_class = self.get_model_class() | ||
return model_class.objects.bulk_create( # type: ignore[attr-defined] | ||
objs=[model_class(**data) for data in validated_data], | ||
batch_size=self.batch_size, | ||
) | ||
|
||
def update( | ||
self, | ||
instance: t.List[AnyModel], | ||
validated_data: t.List[t.Dict[str, t.Any]], | ||
): | ||
"""Bulk update many instances of a model. | ||
https://www.django-rest-framework.org/api-guide/serializers/#customizing-multiple-update | ||
Args: | ||
instance: The models to update. | ||
validated_data: The field-value pairs to update for each model. | ||
Returns: | ||
The models. | ||
""" | ||
|
||
# Models and data must have equal length and be ordered the same! | ||
for model, data in zip(instance, validated_data): | ||
for field, value in data.items(): | ||
setattr(model, field, value) | ||
|
||
model_class = self.get_model_class() | ||
model_class.objects.bulk_update( # type: ignore[attr-defined] | ||
objs=instance, | ||
fields={field for data in validated_data for field in data.keys()}, | ||
batch_size=self.batch_size, | ||
) | ||
|
||
return instance | ||
|
||
def validate(self, attrs: t.List[t.Dict[str, t.Any]]): | ||
# If performing a bulk create. | ||
if self.instance is None: | ||
if len(attrs) == 0: | ||
raise _ValidationError("Nothing to create.") | ||
|
||
# Else, performing a bulk update. | ||
else: | ||
if len(attrs) == 0: | ||
raise _ValidationError("Nothing to update.") | ||
if len(attrs) != len(self.instance): | ||
raise _ValidationError("Some models do not exist.") | ||
|
||
return attrs | ||
|
||
# pylint: disable-next=useless-parent-delegation,arguments-renamed | ||
def to_representation(self, instance: t.List[AnyModel]): | ||
return super().to_representation(instance) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.