Features: 1) Add app_name attribute in multiple urls.py files across apps to support namespacing;

Fixes: 1) Simplify Prometheus and GraphQL path definitions in `evibes/api_urls.py`;

Extra: 1) Add line breaks across multiple files for improved code readability.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-06-29 20:03:33 +03:00
parent 7ff62cea0e
commit 856f2ff516
15 changed files with 53 additions and 5 deletions

View file

@ -28,6 +28,7 @@ class Post(NiceModel):
tags (ManyToManyField): Tags associated with the post for categorization. tags (ManyToManyField): Tags associated with the post for categorization.
""" """
is_publicly_visible = True is_publicly_visible = True
author: ForeignKey = ForeignKey( author: ForeignKey = ForeignKey(
@ -112,6 +113,7 @@ class PostTag(NiceModel):
verbose_name (str): Human-readable singular name of the PostTag model. verbose_name (str): Human-readable singular name of the PostTag model.
verbose_name_plural (str): Human-readable plural name of the PostTag model. verbose_name_plural (str): Human-readable plural name of the PostTag model.
""" """
is_publicly_visible = True is_publicly_visible = True
tag_name: CharField = CharField( tag_name: CharField = CharField(

View file

@ -3,6 +3,8 @@ from rest_framework.routers import DefaultRouter
from blog.viewsets import PostViewSet from blog.viewsets import PostViewSet
app_name = "blog"
payment_router = DefaultRouter() payment_router = DefaultRouter()
payment_router.register(prefix=r"posts", viewset=PostViewSet, basename="posts") payment_router.register(prefix=r"posts", viewset=PostViewSet, basename="posts")

View file

@ -23,6 +23,7 @@ class PostViewSet(ReadOnlyModelViewSet):
filterset_class: Defines the set of filters used for filtering Post objects. filterset_class: Defines the set of filters used for filtering Post objects.
additional: Contains additional configuration, such as specific action permissions. additional: Contains additional configuration, such as specific action permissions.
""" """
serializer_class = PostSerializer serializer_class = PostSerializer
permission_classes = (EvibesPermission,) permission_classes = (EvibesPermission,)
queryset = Post.objects.filter(is_active=True) queryset = Post.objects.filter(is_active=True)

View file

@ -30,6 +30,8 @@ from core.viewsets import (
WishlistViewSet, WishlistViewSet,
) )
app_name = "core"
core_router = DefaultRouter() core_router = DefaultRouter()
core_router.register(r"products", ProductViewSet, basename="products") core_router.register(r"products", ProductViewSet, basename="products")
core_router.register(r"orders", OrderViewSet, basename="orders") core_router.register(r"orders", OrderViewSet, basename="orders")

View file

@ -5,6 +5,8 @@ from core.views import (
GlobalSearchView, GlobalSearchView,
) )
app_name = "core"
urlpatterns = [ urlpatterns = [
path("search/", GlobalSearchView.as_view(), name="global_search"), path("search/", GlobalSearchView.as_view(), name="global_search"),
path("orders/buy_as_business/", BuyAsBusinessView.as_view(), name="request_cursed_url"), path("orders/buy_as_business/", BuyAsBusinessView.as_view(), name="request_cursed_url"),

View file

@ -106,6 +106,7 @@ class CustomGraphQLView(FileUploadGraphQLView):
---------- ----------
None None
""" """
def get_context(self, request): def get_context(self, request):
return request return request
@ -120,6 +121,7 @@ class CustomSwaggerView(SpectacularSwaggerView):
This can be useful in scenarios where the script or reference This can be useful in scenarios where the script or reference
URL needs to be dynamically generated and included in the context. URL needs to be dynamically generated and included in the context.
""" """
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
@ -137,6 +139,7 @@ class CustomRedocView(SpectacularRedocView):
for rendering ReDoc UI is required, specifically adapting the script for rendering ReDoc UI is required, specifically adapting the script
URL for the current request environment. URL for the current request environment.
""" """
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
@ -164,6 +167,7 @@ class SupportedLanguagesView(APIView):
get(self, request): Retrieves the list of supported languages. get(self, request): Retrieves the list of supported languages.
""" """
serializer_class = LanguageSerializer serializer_class = LanguageSerializer
permission_classes = [ permission_classes = [
AllowAny, AllowAny,
@ -218,6 +222,7 @@ class WebsiteParametersView(APIView):
get(request) get(request)
Handles HTTP GET requests to fetch website parameters. Handles HTTP GET requests to fetch website parameters.
""" """
serializer_class = None serializer_class = None
permission_classes = [ permission_classes = [
AllowAny, AllowAny,
@ -253,6 +258,7 @@ class CacheOperatorView(APIView):
post(request, *args, **kwargs): Handles HTTP POST requests to set cache post(request, *args, **kwargs): Handles HTTP POST requests to set cache
data based on the provided key and timeout. data based on the provided key and timeout.
""" """
serializer_class = CacheOperatorSerializer serializer_class = CacheOperatorSerializer
permission_classes = [ permission_classes = [
AllowAny, AllowAny,
@ -294,6 +300,7 @@ class ContactUsView(APIView):
post: Handles POST requests to process form submissions. post: Handles POST requests to process form submissions.
""" """
serializer_class = ContactUsSerializer serializer_class = ContactUsSerializer
renderer_classes = [ renderer_classes = [
CamelCaseJSONRenderer, CamelCaseJSONRenderer,
@ -326,6 +333,7 @@ class RequestCursedURLView(APIView):
Methods: Methods:
post: Handles the POST request to validate the URL, fetch its data if valid, and returns the processed response. post: Handles the POST request to validate the URL, fetch its data if valid, and returns the processed response.
""" """
permission_classes = [ permission_classes = [
AllowAny, AllowAny,
] ]
@ -411,6 +419,7 @@ class BuyAsBusinessView(APIView):
post(request, *_args, **kwargs): post(request, *_args, **kwargs):
Handles the post request to process a business purchase. Handles the post request to process a business purchase.
""" """
@ratelimit(key="ip", rate="2/h", block=True) @ratelimit(key="ip", rate="2/h", block=True)
def post(self, request, *_args, **kwargs): def post(self, request, *_args, **kwargs):
serializer = BuyAsBusinessOrderSerializer(data=request.data) serializer = BuyAsBusinessOrderSerializer(data=request.data)

View file

@ -131,6 +131,7 @@ class EvibesViewSet(ModelViewSet):
Returns the serializer class for the current action or the default Returns the serializer class for the current action or the default
serializer class from the parent ModelViewSet. serializer class from the parent ModelViewSet.
""" """
action_serializer_classes: dict = {} action_serializer_classes: dict = {}
additional: dict = {} additional: dict = {}
permission_classes = [EvibesPermission] permission_classes = [EvibesPermission]
@ -162,6 +163,7 @@ class AttributeGroupViewSet(EvibesViewSet):
specific serializer classes, allowing customization of serialization specific serializer classes, allowing customization of serialization
behavior for certain actions. behavior for certain actions.
""" """
queryset = AttributeGroup.objects.all() queryset = AttributeGroup.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["is_active"] filterset_fields = ["is_active"]
@ -193,6 +195,7 @@ class AttributeViewSet(EvibesViewSet):
specific actions, such as returning less detailed data for a `list` specific actions, such as returning less detailed data for a `list`
action. action.
""" """
queryset = Attribute.objects.all() queryset = Attribute.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["group", "value_type", "is_active"] filterset_fields = ["group", "value_type", "is_active"]
@ -220,6 +223,7 @@ class AttributeValueViewSet(EvibesViewSet):
action_serializer_classes (dict): A dictionary mapping action names to their corresponding action_serializer_classes (dict): A dictionary mapping action names to their corresponding
serializer classes. serializer classes.
""" """
queryset = AttributeValue.objects.all() queryset = AttributeValue.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["attribute", "is_active"] filterset_fields = ["attribute", "is_active"]
@ -258,6 +262,7 @@ class CategoryViewSet(EvibesViewSet):
and filtering out inactive categories for users without sufficient and filtering out inactive categories for users without sufficient
permissions. permissions.
""" """
queryset = Category.objects.all().prefetch_related("parent", "children", "attributes", "tags") queryset = Category.objects.all().prefetch_related("parent", "children", "attributes", "tags")
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_class = CategoryFilter filterset_class = CategoryFilter
@ -294,6 +299,7 @@ class BrandViewSet(EvibesViewSet):
to their corresponding serializer classes. The "list" action to their corresponding serializer classes. The "list" action
uses the BrandSimpleSerializer class. uses the BrandSimpleSerializer class.
""" """
queryset = Brand.objects.all() queryset = Brand.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_class = BrandFilter filterset_class = BrandFilter
@ -328,6 +334,7 @@ class ProductViewSet(EvibesViewSet):
get_object: Fetches a single object based on its identifier, applying permissions. get_object: Fetches a single object based on its identifier, applying permissions.
feedbacks: Fetches feedback associated with a specific product. feedbacks: Fetches feedback associated with a specific product.
""" """
queryset = Product.objects.prefetch_related("tags", "attributes", "stocks", "images").all() queryset = Product.objects.prefetch_related("tags", "attributes", "stocks", "images").all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_class = ProductFilter filterset_class = ProductFilter
@ -402,6 +409,7 @@ class VendorViewSet(EvibesViewSet):
action_serializer_classes: A dictionary mapping specific actions action_serializer_classes: A dictionary mapping specific actions
(e.g., "list") to custom serializer classes for those actions. (e.g., "list") to custom serializer classes for those actions.
""" """
queryset = Vendor.objects.all() queryset = Vendor.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["name", "markup_percent", "is_active"] filterset_fields = ["name", "markup_percent", "is_active"]
@ -433,6 +441,7 @@ class FeedbackViewSet(EvibesViewSet):
serializer classes. For example, the "list" action uses serializer classes. For example, the "list" action uses
`FeedbackSimpleSerializer`. `FeedbackSimpleSerializer`.
""" """
queryset = Feedback.objects.all() queryset = Feedback.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_class = FeedbackFilter filterset_class = FeedbackFilter
@ -495,6 +504,7 @@ class OrderViewSet(EvibesViewSet):
bulk_remove_order_products: Removes multiple products with optional attributes from bulk_remove_order_products: Removes multiple products with optional attributes from
an order. an order.
""" """
lookup_field = "lookup_value" lookup_field = "lookup_value"
lookup_url_kwarg = "lookup_value" lookup_url_kwarg = "lookup_value"
queryset = Order.objects.prefetch_related("order_products").all() queryset = Order.objects.prefetch_related("order_products").all()
@ -692,6 +702,7 @@ class OrderProductViewSet(EvibesViewSet):
do_feedback: Custom action to add, remove, or manage feedback for do_feedback: Custom action to add, remove, or manage feedback for
an OrderProduct instance. an OrderProduct instance.
""" """
queryset = OrderProduct.objects.all() queryset = OrderProduct.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["order", "product", "status", "is_active"] filterset_fields = ["order", "product", "status", "is_active"]
@ -756,6 +767,7 @@ class ProductImageViewSet(EvibesViewSet):
serializer classes. For the "list" action, ProductImageSimpleSerializer serializer classes. For the "list" action, ProductImageSimpleSerializer
is used. is used.
""" """
queryset = ProductImage.objects.all() queryset = ProductImage.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["product", "priority", "is_active"] filterset_fields = ["product", "priority", "is_active"]
@ -785,6 +797,7 @@ class PromoCodeViewSet(EvibesViewSet):
action_serializer_classes: A dictionary mapping specific actions (like action_serializer_classes: A dictionary mapping specific actions (like
"list") to their corresponding serializer classes. "list") to their corresponding serializer classes.
""" """
queryset = PromoCode.objects.all() queryset = PromoCode.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["code", "discount_amount", "discount_percent", "start_time", "end_time", "used_on", "is_active"] filterset_fields = ["code", "discount_amount", "discount_percent", "start_time", "end_time", "used_on", "is_active"]
@ -812,6 +825,7 @@ class PromotionViewSet(EvibesViewSet):
queryset management, filter backends, and serializer customization for handling queryset management, filter backends, and serializer customization for handling
different views or actions efficiently. different views or actions efficiently.
""" """
queryset = Promotion.objects.all() queryset = Promotion.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["name", "discount_percent", "is_active"] filterset_fields = ["name", "discount_percent", "is_active"]
@ -842,6 +856,7 @@ class StockViewSet(EvibesViewSet):
to their respective serializers. For the "list" action, to their respective serializers. For the "list" action,
StockSimpleSerializer is used. StockSimpleSerializer is used.
""" """
queryset = Stock.objects.all() queryset = Stock.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["vendor", "product", "sku", "is_active"] filterset_fields = ["vendor", "product", "sku", "is_active"]
@ -891,6 +906,7 @@ class WishlistViewSet(EvibesViewSet):
bulk_remove_wishlist_products(request, **kwargs) bulk_remove_wishlist_products(request, **kwargs)
Removes multiple products from a specific wishlist. Removes multiple products from a specific wishlist.
""" """
queryset = Wishlist.objects.all() queryset = Wishlist.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["user", "is_active"] filterset_fields = ["user", "is_active"]
@ -1006,6 +1022,7 @@ class AddressViewSet(EvibesViewSet):
serializer_class: Default serializer class for address objects. serializer_class: Default serializer class for address objects.
additional: Dictionary of additional options for this viewset. additional: Dictionary of additional options for this viewset.
""" """
pagination_class = None pagination_class = None
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_class = AddressFilter filterset_class = AddressFilter
@ -1085,6 +1102,7 @@ class ProductTagViewSet(EvibesViewSet):
'list') to custom serializers. Utilizes ProductTagSimpleSerializer 'list') to custom serializers. Utilizes ProductTagSimpleSerializer
for the 'list' action. for the 'list' action.
""" """
queryset = ProductTag.objects.all() queryset = ProductTag.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["tag_name", "is_active"] filterset_fields = ["tag_name", "is_active"]

View file

@ -18,11 +18,8 @@ from evibes.settings import SPECTACULAR_PLATFORM_SETTINGS
urlpatterns = [ urlpatterns = [
path(r"health/", include("health_check.urls", namespace="health_check")), path(r"health/", include("health_check.urls", namespace="health_check")),
path("prometheus/", include("django_prometheus.urls", namespace="prometheus")), path("prometheus/", include("django_prometheus.urls")),
path( path(r"graphql/", csrf_exempt(CustomGraphQLView.as_view(graphiql=True, schema=schema)), name="graphql-platform"),
r"graphql/",
csrf_exempt(CustomGraphQLView.as_view(graphiql=True, schema=schema)), name="graphql-platform"
),
path( path(
r"docs/", r"docs/",
SpectacularAPIView.as_view(urlconf="evibes.api_urls", custom_settings=SPECTACULAR_PLATFORM_SETTINGS), SpectacularAPIView.as_view(urlconf="evibes.api_urls", custom_settings=SPECTACULAR_PLATFORM_SETTINGS),

View file

@ -4,6 +4,8 @@ from rest_framework.routers import DefaultRouter
from payments.views import CallbackAPIView, DepositView from payments.views import CallbackAPIView, DepositView
from payments.viewsets import TransactionViewSet from payments.viewsets import TransactionViewSet
app_name = "payments"
payment_router = DefaultRouter() payment_router = DefaultRouter()
payment_router.register(prefix=r"transactions", viewset=TransactionViewSet, basename="transactions") payment_router.register(prefix=r"transactions", viewset=TransactionViewSet, basename="transactions")

View file

@ -31,6 +31,7 @@ class DepositView(APIView):
post: Processes the deposit request, validates the request data, ensures post: Processes the deposit request, validates the request data, ensures
user authentication, and creates a transaction. user authentication, and creates a transaction.
""" """
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
logger.debug(request.__dict__) logger.debug(request.__dict__)
serializer = DepositSerializer(data=request.data) serializer = DepositSerializer(data=request.data)
@ -65,6 +66,7 @@ class CallbackAPIView(APIView):
based on the specified gateway. Handles exceptions gracefully by returning based on the specified gateway. Handles exceptions gracefully by returning
a server error response if an unknown gateway or other issues occur. a server error response if an unknown gateway or other issues occur.
""" """
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
logger.debug(request.__dict__) logger.debug(request.__dict__)
try: try:

View file

@ -20,5 +20,6 @@ class TransactionViewSet(ReadOnlyModelViewSet):
the data. Includes custom permissions to restrict access based the data. Includes custom permissions to restrict access based
on ownership and other criteria. on ownership and other criteria.
""" """
serializer_class = TransactionSerializer serializer_class = TransactionSerializer
permission_classes = (EvibesPermission, IsOwner) permission_classes = (EvibesPermission, IsOwner)

View file

@ -79,6 +79,7 @@ class User(AbstractUser, NiceModel):
verbose_name: Sets the human-readable name for singular instances of the model. verbose_name: Sets the human-readable name for singular instances of the model.
verbose_name_plural: Sets the human-readable name for multiple instances of the model. verbose_name_plural: Sets the human-readable name for multiple instances of the model.
""" """
def get_uuid_as_path(self, *args): def get_uuid_as_path(self, *args):
return str(self.uuid) + "/" + args[0] return str(self.uuid) + "/" + args[0]
@ -173,6 +174,7 @@ class Group(BaseGroup):
Meta.verbose_name_plural (str): Human-readable plural name for the Group Meta.verbose_name_plural (str): Human-readable plural name for the Group
model. model.
""" """
class Meta: class Meta:
proxy = True proxy = True
verbose_name = _("group") verbose_name = _("group")
@ -194,6 +196,7 @@ class OutstandingToken(BaseOutstandingToken):
the plural form of that name. the plural form of that name.
""" """
class Meta: class Meta:
proxy = True proxy = True
verbose_name = _("outstanding token") verbose_name = _("outstanding token")
@ -214,6 +217,7 @@ class BlacklistedToken(BaseBlacklistedToken):
Attributes: Attributes:
None None
""" """
class Meta: class Meta:
proxy = True proxy = True
verbose_name = _("blacklisted token") verbose_name = _("blacklisted token")

View file

@ -4,6 +4,8 @@ from rest_framework.routers import DefaultRouter
from vibes_auth.views import TokenObtainPairView, TokenRefreshView, TokenVerifyView from vibes_auth.views import TokenObtainPairView, TokenRefreshView, TokenVerifyView
from vibes_auth.viewsets import UserViewSet from vibes_auth.viewsets import UserViewSet
app_name = "vibes_auth"
auth_router = DefaultRouter() auth_router = DefaultRouter()
auth_router.register(r"users", UserViewSet, basename="users") auth_router.register(r"users", UserViewSet, basename="users")

View file

@ -46,6 +46,7 @@ class TokenObtainPairView(TokenViewBase):
post: Handles HTTP POST requests for token retrieval. This method is post: Handles HTTP POST requests for token retrieval. This method is
subject to rate limiting depending on the global DEBUG setting. subject to rate limiting depending on the global DEBUG setting.
""" """
serializer_class = TokenObtainPairSerializer # type: ignore serializer_class = TokenObtainPairSerializer # type: ignore
_serializer_class = TokenObtainPairSerializer # type: ignore _serializer_class = TokenObtainPairSerializer # type: ignore
@ -80,6 +81,7 @@ class TokenRefreshView(TokenViewBase):
the request. Rate limit settings are defined depending on the request. Rate limit settings are defined depending on
whether the application is in DEBUG mode or not. whether the application is in DEBUG mode or not.
""" """
serializer_class = TokenRefreshSerializer # type: ignore serializer_class = TokenRefreshSerializer # type: ignore
_serializer_class = TokenRefreshSerializer # type: ignore _serializer_class = TokenRefreshSerializer # type: ignore
@ -101,6 +103,7 @@ class TokenVerifyView(TokenViewBase):
user data can also be returned. Errors during token validation result in an appropriate user data can also be returned. Errors during token validation result in an appropriate
error response. error response.
""" """
serializer_class = TokenVerifySerializer # type: ignore serializer_class = TokenVerifySerializer # type: ignore
_serializer_class = TokenVerifySerializer # type: ignore _serializer_class = TokenVerifySerializer # type: ignore

View file

@ -78,6 +78,7 @@ class UserViewSet(
OverflowError, TypeError: OverflowError, TypeError:
Raised for decoding or type conversion issues. Raised for decoding or type conversion issues.
""" """
serializer_class = UserSerializer serializer_class = UserSerializer
queryset = User.objects.filter(is_active=True) queryset = User.objects.filter(is_active=True)
permission_classes = [AllowAny] permission_classes = [AllowAny]