From 7ff62cea0e830e890edd8e31138d8f5b68f0a60a Mon Sep 17 00:00:00 2001 From: Egor fureunoir Gorbunov Date: Sun, 29 Jun 2025 19:56:52 +0300 Subject: [PATCH] Features: 1) Add detailed class-level docstrings for multiple ViewSets and views, improving maintainability and documentation; 2) Introduce namespace for "core_b2b" in URL patterns for better URL resolution. Fixes: 1) Remove unused "prometheus/" URL pattern for cleanup. Extra: Update imports and formats for consistency; refine sitemap functions with explicit docstrings. --- blog/models.py | 39 ++++ blog/viewsets.py | 15 ++ core/views.py | 232 +++++++++++++++++++++++- core/viewsets.py | 398 +++++++++++++++++++++++++++++++++++++++++ evibes/b2b_urls.py | 4 +- payments/views.py | 32 ++++ payments/viewsets.py | 15 ++ vibes_auth/models.py | 89 +++++++++ vibes_auth/views.py | 57 ++++++ vibes_auth/viewsets.py | 40 +++++ 10 files changed, 916 insertions(+), 5 deletions(-) diff --git a/blog/models.py b/blog/models.py index d47853e8..28b15a11 100644 --- a/blog/models.py +++ b/blog/models.py @@ -8,6 +8,26 @@ from core.abstract import NiceModel class Post(NiceModel): + """ + Represents a blog post model extending NiceModel. + + The Post class defines the structure and behavior of a blog post. It includes + attributes for author, title, content, optional file attachment, slug, + and associated tags. The class enforces constraints such as requiring either + content or a file attachment but not both simultaneously. It also supports + automatic slug generation based on the title. This model can be used in + a blogging platform to manage posts created by users. + + Attributes: + is_publicly_visible (bool): Specifies whether the post is visible to the public. + author (ForeignKey): A reference to the user who authored the post. + title (CharField): The title of the post, must be unique and non-empty. + content (MarkdownField): The content of the post written in markdown format. + file (FileField): An optional file attachment for the post. + slug (AutoSlugField): A unique, automatically generated slug based on the title. + tags (ManyToManyField): Tags associated with the post for categorization. + + """ is_publicly_visible = True author: ForeignKey = ForeignKey( @@ -73,6 +93,25 @@ class Post(NiceModel): class PostTag(NiceModel): + """ + Represents a tag associated with a post. + + The PostTag class is used to define and manage tags that can be assigned + to posts. These tags include an internal identifier and a user-friendly + display name. The class supports internationalization for both the internal + identifier and the display name. + + Attributes: + is_publicly_visible (bool): Determines if the tag is visible publicly. + tag_name (CharField): An internal tag identifier for the post tag. It is a required + field with a maximum length of 255 characters. + name (CharField): A user-friendly, unique display name for the post tag + with a maximum length of 255 characters. + + Meta: + verbose_name (str): Human-readable singular name of the PostTag model. + verbose_name_plural (str): Human-readable plural name of the PostTag model. + """ is_publicly_visible = True tag_name: CharField = CharField( diff --git a/blog/viewsets.py b/blog/viewsets.py index 8c30214c..c5b338f3 100644 --- a/blog/viewsets.py +++ b/blog/viewsets.py @@ -8,6 +8,21 @@ from core.permissions import EvibesPermission class PostViewSet(ReadOnlyModelViewSet): + """ + Encapsulates operations for managing and retrieving Post entities in a read-only model view set. + + This class is tailored to handle Post objects that are active and allows filtration based on defined + filters. It integrates with Django's backend filtering system and ensures operations align with the + defined permissions. The view set also includes an additional "retrieve" permission configuration. + + Attributes: + serializer_class: Specifies the serializer to be used for Post objects. + permission_classes: Defines the permissions required to interact with this view set. + queryset: Determines the initial queryset, filtered to include only active Post objects. + filter_backends: Lists the backends to be used for filtering querysets. + filterset_class: Defines the set of filters used for filtering Post objects. + additional: Contains additional configuration, such as specific action permissions. + """ serializer_class = PostSerializer permission_classes = (EvibesPermission,) queryset = Post.objects.filter(is_active=True) diff --git a/core/views.py b/core/views.py index 8315af07..d4711a39 100644 --- a/core/views.py +++ b/core/views.py @@ -53,23 +53,73 @@ from payments.serializers import TransactionProcessSerializer def sitemap_index(request, *args, **kwargs): + """ + Handles the request for the sitemap index and returns an XML response. It ensures the response includes + the appropriate content type header for XML. + + Args: + request: The HTTP request object. + *args: Additional positional arguments passed to the view. + **kwargs: Additional keyword arguments passed to the view. + + Returns: + A response object containing the sitemap index in XML format, with the proper content type set as + "application/xml; charset=utf-8". + """ response = _sitemap_index_view(request, *args, **kwargs) response["Content-Type"] = "application/xml; charset=utf-8" return response def sitemap_detail(request, *args, **kwargs): + """ + Handles the detailed view response for a sitemap. This function processes + the request, fetches the appropriate sitemap detail response, and sets the + Content-Type header for XML responses. + + Args: + request: An HTTP request object containing request metadata, such as + headers and HTTP method. + *args: Additional positional arguments provided dynamically to the + underlying sitemap detail view function. + **kwargs: Additional keyword arguments provided dynamically to the + underlying sitemap detail view function. + + Returns: + HttpResponse: A response object with content representing the requested + sitemap details. The Content-Type header is explicitly set to + "application/xml; charset=utf-8". + """ response = _sitemap_detail_view(request, *args, **kwargs) response["Content-Type"] = "application/xml; charset=utf-8" return response class CustomGraphQLView(FileUploadGraphQLView): + """ + A custom GraphQL view class that extends the functionality of FileUploadGraphQLView. + + This class serves as a customization extension of FileUploadGraphQLView that allows modification + or enhancement of specific behaviors, particularly the context handling for GraphQL requests. + + Attributes + ---------- + None + """ def get_context(self, request): return request class CustomSwaggerView(SpectacularSwaggerView): + """ + CustomSwaggerView is a subclass of SpectacularSwaggerView. + + This class overrides the `get_context_data` method to + add extra context to the response. It modifies the context by + including the absolute URI of the current request as the `script_url`. + This can be useful in scenarios where the script or reference + URL needs to be dynamically generated and included in the context. + """ def get_context_data(self, **kwargs): # noinspection PyUnresolvedReferences context = super().get_context_data(**kwargs) @@ -78,6 +128,15 @@ class CustomSwaggerView(SpectacularSwaggerView): class CustomRedocView(SpectacularRedocView): + """ + CustomRedocView provides a customized version of the SpectacularRedocView. + + This class extends the SpectacularRedocView to include additional + functionality, such as dynamically setting the `script_url` in the + context data. It is designed to be used where customized behavior + for rendering ReDoc UI is required, specifically adapting the script + URL for the current request environment. + """ def get_context_data(self, **kwargs): # noinspection PyUnresolvedReferences context = super().get_context_data(**kwargs) @@ -87,6 +146,24 @@ class CustomRedocView(SpectacularRedocView): @extend_schema_view(**LANGUAGE_SCHEMA) class SupportedLanguagesView(APIView): + """ + Handles retrieving the list of supported languages. + + This class provides an endpoint to return available languages information. + It is configured with relevant serializers, permission classes, and renderers + for flexibility in response formats and access permissions. The endpoint + supports retrieving the list of languages with their respective codes, names, + and flags. + + Attributes: + serializer_class (Serializer): Serializer used for formatting the response data. + permission_classes (list): Permissions applied to restrict the endpoint access. + renderer_classes (list): Renderers available for formatting response output. + + Methods: + get(self, request): Retrieves the list of supported languages. + + """ serializer_class = LanguageSerializer permission_classes = [ AllowAny, @@ -117,6 +194,30 @@ class SupportedLanguagesView(APIView): @extend_schema_view(**PARAMETERS_SCHEMA) class WebsiteParametersView(APIView): + """ + Handles operations related to website parameters. + + This class is a Django Rest Framework view that allows clients to retrieve + the parameters of a website. It uses different renderers to present the data + in various formats. The view is publicly accessible. + + Attributes + ---------- + serializer_class + A placeholder for a DRF serializer, it is set to None since no serializer + is explicitly used in this view. + permission_classes + A list indicating the permissions required to access this view. In this case, + `AllowAny`, meaning the view is open to everyone. + renderer_classes + A list of renderers available for this view, supporting CamelCase JSON, + multipart forms, XML, and YAML formats. + + Methods + ------- + get(request) + Handles HTTP GET requests to fetch website parameters. + """ serializer_class = None permission_classes = [ AllowAny, @@ -134,6 +235,24 @@ class WebsiteParametersView(APIView): @extend_schema_view(**CACHE_SCHEMA) class CacheOperatorView(APIView): + """ + View for managing cache operations. + + This class provides an API view for handling cache operations such as setting cache + data with a specified key and timeout. It leverages multiple renderer classes for + serializing outputs in various formats. + + Attributes: + serializer_class (type): Serializer to validate and deserialize input data. + permission_classes (list): List of permission classes to apply access + restrictions. + renderer_classes (list): List of renderer classes to serialize the output + in desired formats. + + Methods: + post(request, *args, **kwargs): Handles HTTP POST requests to set cache + data based on the provided key and timeout. + """ serializer_class = CacheOperatorSerializer permission_classes = [ AllowAny, @@ -159,6 +278,22 @@ class CacheOperatorView(APIView): @extend_schema_view(**CONTACT_US_SCHEMA) class ContactUsView(APIView): + """ + Handles contact us form submissions via a REST API. + + This view processes user submissions for a "Contact Us" form. It validates the received + data using a serializer, applies rate limiting for IP-based requests, and sends emails + asynchronously. The view is prepared to handle multiple response formats using configured + renderers. + + Attributes: + serializer_class: The serializer class used to validate incoming data. + renderer_classes: A list of renderers to support multiple response formats. + + Methods: + post: Handles POST requests to process form submissions. + + """ serializer_class = ContactUsSerializer renderer_classes = [ CamelCaseJSONRenderer, @@ -178,6 +313,19 @@ class ContactUsView(APIView): @extend_schema_view(**REQUEST_CURSED_URL_SCHEMA) class RequestCursedURLView(APIView): + """ + Handles requests for processing and validating URLs from incoming POST requests. + + Particularly intended for validating and processing URLs provided by clients. It utilizes rate-limiting, caching, and + various response format renderers to optimize performance and ensure safe handling of external data. + + Attributes: + permission_classes (list): Specifies the permissions required to access this view. + renderer_classes (list): Configures the response format renderers available for this view. + + Methods: + post: Handles the POST request to validate the URL, fetch its data if valid, and returns the processed response. + """ permission_classes = [ AllowAny, ] @@ -217,8 +365,21 @@ class RequestCursedURLView(APIView): @extend_schema_view(**SEARCH_SCHEMA) class GlobalSearchView(APIView): """ - A global search endpoint. - It returns a response grouping matched items by index. + Class-based view for handling global search functionality. + + This class is designed to process search queries from HTTP GET requests. It is + capable of rendering results in multiple formats including CamelCase JSON, + MultiPart, XML, and YAML. The class uses a custom schema for API documentation + and processes search queries passed as parameters in the request. + + Attributes: + renderer_classes (list): List of renderer classes used to serialize responses + into various formats such as CamelCase JSON, MultiPart, XML, and YAML. + + Methods: + get: Handles HTTP GET requests by processing the search query and returning + formatted search results. + """ renderer_classes = [ @@ -234,6 +395,22 @@ class GlobalSearchView(APIView): @extend_schema_view(**BUY_AS_BUSINESS_SCHEMA) class BuyAsBusinessView(APIView): + """ + View for buying as a business. + + This view handles the logic of creating orders and processing transactions when a + business makes a purchase. It ensures that the request data is properly validated + and processed, handles the creation of the order, and starts the transaction process. + The view also restricts the rate of requests based on the client's IP address + to prevent abuse. + + Attributes: + schema (class): Extended schema for API documentation. + + Methods: + post(request, *_args, **kwargs): + Handles the post request to process a business purchase. + """ @ratelimit(key="ip", rate="2/h", block=True) def post(self, request, *_args, **kwargs): serializer = BuyAsBusinessOrderSerializer(data=request.data) @@ -258,6 +435,25 @@ class BuyAsBusinessView(APIView): def download_digital_asset_view(request, *args, **kwargs): + """ + Handles the downloading of a digital asset associated with an order. Ensures that users + are permitted to download the asset only once. Validates the request, retrieves the file, + and serves it as a downloadable response. Returns appropriate error responses for different + failure scenarios. + + Args: + request: The HTTP request object containing information about the client request. + *args: Additional positional arguments. + **kwargs: Additional keyword arguments. + + Raises: + BadRequest: If the digital asset has already been downloaded. + DigitalAssetDownload.DoesNotExist: If the requested digital asset cannot be found. + + Returns: + A FileResponse containing the digital asset file if the request is valid. Returns + a JsonResponse with an error message if an error occurs during the process. + """ try: uuid = force_str(urlsafe_base64_decode(kwargs["encoded_uuid"])) download = DigitalAssetDownload.objects.get(order_product__uuid=uuid) @@ -295,6 +491,23 @@ def download_digital_asset_view(request, *args, **kwargs): def favicon_view(request, *args, **kwargs): + """ + Handles requests for the favicon of a website. This function attempts to serve the favicon + file located in the static directory of the project. If the favicon file is not found, + an HTTP 404 error is raised to indicate the resource is unavailable. + + Args: + request: The HTTP request object. + *args: Additional positional arguments that are ignored in this function. + **kwargs: Additional keyword arguments that are ignored in this function. + + Returns: + FileResponse: A file response containing the favicon image with the content-type + "image/x-icon". + + Raises: + Http404: Raised if the favicon file is not found. + """ try: favicon_path = os.path.join(settings.BASE_DIR, "static/favicon.png") return FileResponse(open(favicon_path, "rb"), content_type="image/x-icon") @@ -303,4 +516,19 @@ def favicon_view(request, *args, **kwargs): def index(request, *args, **kwargs): + """ + Redirects the request to the admin index page. + + The function handles incoming HTTP requests and redirects them to the Django + admin interface index page. It uses Django's `redirect` function for handling + the HTTP redirection. + + Args: + request: The HttpRequest object representing the incoming request. + *args: Additional positional arguments, if any. + **kwargs: Additional keyword arguments, if any. + + Returns: + HttpResponseRedirect: An HTTP response that redirects to the admin index. + """ return redirect("admin:index") diff --git a/core/viewsets.py b/core/viewsets.py index ee3db6ad..0372ca51 100644 --- a/core/viewsets.py +++ b/core/viewsets.py @@ -111,6 +111,26 @@ logger = logging.getLogger("django.request") class EvibesViewSet(ModelViewSet): + """ + Defines a viewset for managing Evibes-related operations. + + The EvibesViewSet class inherits from ModelViewSet and provides functionality + for handling actions and operations on Evibes entities. It includes support + for dynamic serializer classes based on the current action, customizable + permissions, and rendering formats. + + Attributes: + action_serializer_classes: Dictionary mapping action names to their specific + serializer classes. + additional: Dictionary to hold additional data related to the view. + permission_classes: List of permission classes applicable to this viewset. + renderer_classes: List of renderer classes supported for response formatting. + + Methods: + get_serializer_class(self): + Returns the serializer class for the current action or the default + serializer class from the parent ModelViewSet. + """ action_serializer_classes: dict = {} additional: dict = {} permission_classes = [EvibesPermission] @@ -122,6 +142,26 @@ class EvibesViewSet(ModelViewSet): @extend_schema_view(**ATTRIBUTE_GROUP_SCHEMA) class AttributeGroupViewSet(EvibesViewSet): + """ + Represents a viewset for managing AttributeGroup objects. + + Handles operations related to AttributeGroup, including filtering, + serialization, and retrieval of data. This class is part of the + application's API layer and provides a standardized way to process + requests and responses for AttributeGroup data. + + Attributes: + queryset (QuerySet): QuerySet for retrieving all AttributeGroup objects. + filter_backends (list): List of filter backends used to process filters + in requests. + filterset_fields (list): List of fields on which filtering operations + can be performed. + serializer_class (Serializer): Default serializer class used for + processing AttributeGroup data during non-list view operations. + action_serializer_classes (dict): Mapping of view actions to their + specific serializer classes, allowing customization of serialization + behavior for certain actions. + """ queryset = AttributeGroup.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["is_active"] @@ -133,6 +173,26 @@ class AttributeGroupViewSet(EvibesViewSet): @extend_schema_view(**ATTRIBUTE_SCHEMA) class AttributeViewSet(EvibesViewSet): + """ + Handles operations related to Attribute objects within the application. + + Provides a set of API endpoints to interact with Attribute data. This class + manages querying, filtering, and serialization of Attribute objects, allowing + dynamic control over the data returned, such as filtering by specific fields + or retrieving detailed versus simplified information depending on the request. + + Attributes: + queryset: The base QuerySet used to represent the set of Attribute + objects available to this viewset. + filter_backends: Defines the backends used for filtering request data, + enabling query flexibility. + filterset_fields: A list of model fields that can be filtered via the API. + serializer_class: Represents the serializer used by default for + serialization and deserialization of Attribute data. + action_serializer_classes: A mapping that defines serializers used for + specific actions, such as returning less detailed data for a `list` + action. + """ queryset = Attribute.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["group", "value_type", "is_active"] @@ -144,6 +204,22 @@ class AttributeViewSet(EvibesViewSet): @extend_schema_view(**ATTRIBUTE_VALUE_SCHEMA) class AttributeValueViewSet(EvibesViewSet): + """ + A viewset for managing AttributeValue objects. + + This viewset provides functionality for listing, retrieving, creating, updating, and deleting + AttributeValue objects. It integrates with Django REST Framework's viewset mechanisms and uses + appropriate serializers for different actions. Filtering capabilities are provided through the + DjangoFilterBackend. + + Attributes: + queryset (QuerySet): The base queryset for AttributeValue objects. + filter_backends (list): A list of filtering backends applied to the viewset. + filterset_fields (list): Fields of the model that can be used for filtering. + serializer_class (Serializer): The default serializer class for the viewset. + action_serializer_classes (dict): A dictionary mapping action names to their corresponding + serializer classes. + """ queryset = AttributeValue.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["attribute", "is_active"] @@ -155,6 +231,33 @@ class AttributeValueViewSet(EvibesViewSet): @extend_schema_view(**CATEGORY_SCHEMA) class CategoryViewSet(EvibesViewSet): + """ + Manages views for Category-related operations. + + The CategoryViewSet class is responsible for handling operations related to + the Category model in the system. It supports retrieving, filtering, and + serializing category data. The viewset also enforces permissions to ensure + that only authorized users can access specific data. + + Attributes: + queryset: The base queryset used to retrieve category data, including + prefetching related objects such as parent, children, attributes, + and tags. + filter_backends: A list of backends for applying filters to the category + data. + filterset_class: The filter class used to define filtering behavior for + the category queryset. + serializer_class: The default serializer class used for category objects + when no specific action serializer is applied. + action_serializer_classes: A dictionary mapping specific viewset actions + (e.g., "list") to their corresponding serializer classes. + + Methods: + get_queryset(): + Retrieves the queryset for the viewset, applying permission checks + and filtering out inactive categories for users without sufficient + permissions. + """ queryset = Category.objects.all().prefetch_related("parent", "children", "attributes", "tags") filter_backends = [DjangoFilterBackend] filterset_class = CategoryFilter @@ -171,6 +274,26 @@ class CategoryViewSet(EvibesViewSet): class BrandViewSet(EvibesViewSet): + """ + Represents a viewset for managing Brand instances. + + This class provides functionality for querying, filtering, and + serializing Brand objects. It uses Django's ViewSet framework + to simplify the implementation of API endpoints for Brand objects. + + Attributes: + queryset: The base queryset containing all Brand instances. + filter_backends: A list of filtering backends to apply to the + queryset. The default is [DjangoFilterBackend]. + filterset_class: The filter class used to define the filtering + logic for this viewset. The default is BrandFilter. + serializer_class: The default serializer class used for the + detailed representation of Brand objects. The default is + BrandDetailSerializer. + action_serializer_classes: A dictionary mapping specific actions + to their corresponding serializer classes. The "list" action + uses the BrandSimpleSerializer class. + """ queryset = Brand.objects.all() filter_backends = [DjangoFilterBackend] filterset_class = BrandFilter @@ -182,6 +305,29 @@ class BrandViewSet(EvibesViewSet): @extend_schema_view(**PRODUCT_SCHEMA) class ProductViewSet(EvibesViewSet): + """ + Manages operations related to the `Product` model in the system. + + This class provides a viewset for managing products, including their filtering, serialization, + and operations on specific instances. It extends from `EvibesViewSet` to utilize common + functionality and integrates with Django REST framework for RESTful API operations. + Includes methods for retrieving product details, applying permissions, and accessing + related feedback of a product. + + Attributes: + queryset: The base queryset to retrieve `Product` objects with prefetch optimization. + filter_backends: Specifies the filtering mechanism for the list views. + filterset_class: Defines the filter class to be used for filtering products. + serializer_class: The default serializer class for product details. + action_serializer_classes: Specific serializer mappings for action methods. + lookup_field: Field representing the object's lookup value in URLs. + lookup_url_kwarg: Field key used to extract the object's lookup value from URL. + + Methods: + get_queryset: Retrieves the queryset with user-specific filtering applied. + get_object: Fetches a single object based on its identifier, applying permissions. + feedbacks: Fetches feedback associated with a specific product. + """ queryset = Product.objects.prefetch_related("tags", "attributes", "stocks", "images").all() filter_backends = [DjangoFilterBackend] filterset_class = ProductFilter @@ -237,6 +383,25 @@ class ProductViewSet(EvibesViewSet): class VendorViewSet(EvibesViewSet): + """ + Represents a viewset for managing Vendor objects. + + This viewset allows fetching, filtering, and serializing Vendor data. + It defines the queryset, filter configurations, and serializer classes + used to handle different actions. The purpose of this class is to + provide streamlined access to Vendor-related resources through the + Django REST framework. + + Attributes: + queryset: A QuerySet containing all Vendor objects. + filter_backends: A list containing configured filter backends. + filterset_fields: A list of fields that can be used for filtering + Vendor records. + serializer_class: The default serializer class used for this + viewset. + action_serializer_classes: A dictionary mapping specific actions + (e.g., "list") to custom serializer classes for those actions. + """ queryset = Vendor.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["name", "markup_percent", "is_active"] @@ -248,6 +413,26 @@ class VendorViewSet(EvibesViewSet): @extend_schema_view(**FEEDBACK_SCHEMA) class FeedbackViewSet(EvibesViewSet): + """ + Representation of a view set handling Feedback objects. + + This class manages operations related to Feedback objects, including listing, + filtering, and retrieving details. The purpose of this view set is to provide + different serializers for different actions and implement permission-based + handling of accessible Feedback objects. It extends the base `EvibesViewSet` + and makes use of Django's filtering system for querying data. + + Attributes: + queryset: The base queryset for Feedback objects used in this view set. + filter_backends: List of filter backends to apply, specifically + `DjangoFilterBackend` for this view set. + filterset_class: Class specifying the filter set used for querying + Feedback objects. + serializer_class: Default serializer class used for this view set. + action_serializer_classes: A dictionary mapping action names to specific + serializer classes. For example, the "list" action uses + `FeedbackSimpleSerializer`. + """ queryset = Feedback.objects.all() filter_backends = [DjangoFilterBackend] filterset_class = FeedbackFilter @@ -265,6 +450,51 @@ class FeedbackViewSet(EvibesViewSet): @extend_schema_view(**ORDER_SCHEMA) class OrderViewSet(EvibesViewSet): + """ + ViewSet for managing orders and related operations. + + This class provides functionality to retrieve, modify, and manage order objects. + It includes various endpoints for handling order operations such as adding or + removing products, performing purchases for registered as well as unregistered + users, and retrieving the current authenticated user's pending orders. + + The ViewSet uses multiple serializers based on the specific action being + performed and enforces permissions accordingly while interacting with order data. + + Attributes: + lookup_field (str): Field name used for performing object lookup. + lookup_url_kwarg (str): URL keyword argument used for object lookup. Defaults + to `lookup_field`. + queryset (QuerySet): Default queryset for retrieving order objects, with + prefetched related order products. + filter_backends (list): List of backends applied for filtering the queryset. + filterset_class (type): Filtering class applied to the queryset for request-based + customizations. + serializer_class (type): Default serializer used if no specific serializer is + defined for an action. + action_serializer_classes (dict): Mapping of actions to their respective serializers. + Used to determine the serializer dynamically based on the requested action. + additional (dict): Additional settings for specific actions. + + Methods: + get_serializer_class: Returns the serializer class based on the specific + action being requested. + get_queryset: Adjusts the queryset based on the request user's permissions, + favoring anonymous or limited query access for unauthenticated users. + get_object: Retrieves a specific order object based on the lookup value, either + its UUID or a human-readable ID. + current: Retrieves the authenticated user's current pending order. + buy: Processes an order purchase for an authenticated user with optional parameters + such as balance and payment overrides, promocodes, and billing/shipping addresses. + buy_unregistered: Processes an order purchase for unauthenticated users with product, + customer details, and payment information. + add_order_product: Adds a product, with optional attributes, to an order specified by UUID. + remove_order_product: Removes a product, with optional attributes, from an order specified + by UUID. + bulk_add_order_products: Adds multiple products with optional attributes to an order. + bulk_remove_order_products: Removes multiple products with optional attributes from + an order. + """ lookup_field = "lookup_value" lookup_url_kwarg = "lookup_value" queryset = Order.objects.prefetch_related("order_products").all() @@ -435,6 +665,33 @@ class OrderViewSet(EvibesViewSet): @extend_schema_view(**ORDER_PRODUCT_SCHEMA) class OrderProductViewSet(EvibesViewSet): + """ + Provides a viewset for managing OrderProduct entities. + + This viewset enables CRUD operations and custom actions specific to the + OrderProduct model. It includes filtering, permission checks, and + serializer switching based on the requested action. Additionally, it + provides a detailed action for handling feedback on OrderProduct + instances. + + Attributes: + queryset (QuerySet): The base queryset for OrderProduct objects. + filter_backends (list): Backends responsible for handling filtering + mechanisms. + filterset_fields (list[str]): Fields available for API filtering. + serializer_class (Serializer): Default serializer class for CRUD + operations. + action_serializer_classes (dict[str, Serializer]): Mapping of + specific actions to their corresponding serializer classes. + + Methods: + get_queryset: Overrides the default queryset to enforce user + permissions. + + Actions: + do_feedback: Custom action to add, remove, or manage feedback for + an OrderProduct instance. + """ queryset = OrderProduct.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["order", "product", "status", "is_active"] @@ -478,6 +735,27 @@ class OrderProductViewSet(EvibesViewSet): class ProductImageViewSet(EvibesViewSet): + """ + Manages operations related to Product images in the application. + + This class-based view set provides endpoints to manage and access ProductImage + objects. It supports filtering, serialization, and customized serializers for + different actions to handle ProductImage data. + + Attributes: + queryset (QuerySet): A Django QuerySet consisting of all ProductImage + instances within the system. + filter_backends (list): A list of filter backends that determine the + filtering behavior on querysets. Set to [DjangoFilterBackend]. + filterset_fields (list): Fields that can be used for filtering data. + Includes "product", "priority", and "is_active". + serializer_class (Serializer): The default serializer class used for + serializing and deserializing ProductImage data. Set to + ProductImageDetailSerializer. + action_serializer_classes (dict): A mapping of action names to specific + serializer classes. For the "list" action, ProductImageSimpleSerializer + is used. + """ queryset = ProductImage.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["product", "priority", "is_active"] @@ -488,6 +766,25 @@ class ProductImageViewSet(EvibesViewSet): class PromoCodeViewSet(EvibesViewSet): + """ + Manages the retrieval and handling of PromoCode instances through various + API actions. + + This class extends the functionality of the EvibesViewSet to provide a + customized view set for PromoCode objects. It includes filtering capabilities, + utilizes specific serializers for different actions, and limits data access + based on user permissions. The primary purpose is to enable API operations + related to PromoCodes while enforcing security and filtering. + + Attributes: + queryset: A queryset of all PromoCode objects in the database. + filter_backends: Backend classes responsible for filtering queryset data. + filterset_fields: Fields supported for filtering PromoCode data. + serializer_class: The default serializer class used for instances when no + specific action-based serializer is defined. + action_serializer_classes: A dictionary mapping specific actions (like + "list") to their corresponding serializer classes. + """ queryset = PromoCode.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["code", "discount_amount", "discount_percent", "start_time", "end_time", "used_on", "is_active"] @@ -507,6 +804,14 @@ class PromoCodeViewSet(EvibesViewSet): class PromotionViewSet(EvibesViewSet): + """ + Represents a view set for managing promotions. + + This class provides operations to handle retrieval, filtering, and serialization + of promotion objects. It leverages Django REST framework capabilities such as + queryset management, filter backends, and serializer customization for handling + different views or actions efficiently. + """ queryset = Promotion.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["name", "discount_percent", "is_active"] @@ -517,6 +822,26 @@ class PromotionViewSet(EvibesViewSet): class StockViewSet(EvibesViewSet): + """ + Handles operations related to Stock data in the system. + + The StockViewSet class is a viewset that provides methods for retrieving, + filtering, and serializing Stock data. It utilizes Django's filter + backends to enable filtering based on specified fields and supports + custom serializers for different actions. + + Attributes: + queryset (QuerySet): A queryset of all Stock objects. + filter_backends (list): A list of filter backends to be applied. + filterset_fields (list of str): Fields on which the filtering + is permitted. These fields include "vendor", "product", "sku", + and "is_active". + serializer_class (Serializer): The primary serializer used + for Stock detail representation. + action_serializer_classes (dict): A dictionary mapping action names + to their respective serializers. For the "list" action, + StockSimpleSerializer is used. + """ queryset = Stock.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["vendor", "product", "sku", "is_active"] @@ -528,6 +853,44 @@ class StockViewSet(EvibesViewSet): @extend_schema_view(**WISHLIST_SCHEMA) class WishlistViewSet(EvibesViewSet): + """ + ViewSet for managing Wishlist operations. + + The WishlistViewSet provides endpoints for interacting with a user's wish list, + allowing for the retrieval, modification, and customization of products within + the wish list. This ViewSet facilitates functionality such as adding, removing, + and bulk actions for wishlist products. Permission checks are integrated to + ensure that users can only manage their own wishlists, unless explicit permissions + are granted. + + Attributes + ---------- + queryset : QuerySet + The base queryset for retrieving wishlist objects. + filter_backends : list + List of backend filters to apply to the queryset. + filterset_fields : list + Fields for which filtering is allowed in queries. + serializer_class : Serializer + The default serializer class used for wishlist objects. + action_serializer_classes : dict + A map of serializers used for specific actions. + + Methods + ------- + get_queryset() + Retrieves the queryset, filtered based on the user's permissions. + current(request) + Retrieves the currently authenticated user's wishlist. + add_wishlist_product(request, **kwargs) + Adds a product to a specific wishlist. + remove_wishlist_product(request, **kwargs) + Removes a product from a specific wishlist. + bulk_add_wishlist_products(request, **kwargs) + Adds multiple products to a specific wishlist. + bulk_remove_wishlist_products(request, **kwargs) + Removes multiple products from a specific wishlist. + """ queryset = Wishlist.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["user", "is_active"] @@ -628,6 +991,21 @@ class WishlistViewSet(EvibesViewSet): @extend_schema_view(**ADDRESS_SCHEMA) class AddressViewSet(EvibesViewSet): + """ + This class provides viewset functionality for managing `Address` objects. + + The AddressViewSet class enables CRUD operations, filtering, and custom actions + related to address entities. It includes specialized behaviors for different HTTP + methods, serializer overrides, and permission handling based on the request context. + + Attributes: + pagination_class: Specifies pagination class for the viewset, set to None. + filter_backends: List of backend classes for filtering querysets. + filterset_class: Specifies the filter class for filtering address objects. + queryset: Default queryset containing all Address objects. + serializer_class: Default serializer class for address objects. + additional: Dictionary of additional options for this viewset. + """ pagination_class = None filter_backends = [DjangoFilterBackend] filterset_class = AddressFilter @@ -687,6 +1065,26 @@ class AddressViewSet(EvibesViewSet): class ProductTagViewSet(EvibesViewSet): + """ + Handles operations related to Product Tags within the application. + + This class provides functionality for retrieving, filtering, and serializing + Product Tag objects. It supports flexible filtering on specific attributes + using the specified filter backend and dynamically uses different serializers + based on the action being performed. + + Attributes: + queryset: The base queryset containing all ProductTag objects. + filter_backends: A list of backends used to filter the queryset. + filterset_fields: Fields available for filtering the queryset. Includes + 'tag_name' for filtering by the name of the tag, and 'is_active' for + filtering active/inactive tags. + serializer_class: The default serializer class used when no specific + serializer is defined for an action. + action_serializer_classes: A dictionary mapping specific actions (e.g., + 'list') to custom serializers. Utilizes ProductTagSimpleSerializer + for the 'list' action. + """ queryset = ProductTag.objects.all() filter_backends = [DjangoFilterBackend] filterset_fields = ["tag_name", "is_active"] diff --git a/evibes/b2b_urls.py b/evibes/b2b_urls.py index 8bd89af0..aeeeee23 100644 --- a/evibes/b2b_urls.py +++ b/evibes/b2b_urls.py @@ -7,8 +7,6 @@ from core.views import CustomRedocView, CustomSwaggerView, favicon_view from evibes.settings import SPECTACULAR_B2B_SETTINGS urlpatterns = [ - # path(r'graphql/', csrf_exempt(CustomGraphQLView.as_view(graphiql=True, schema=schema))), - path("prometheus/", include("django_prometheus.urls")), path( r"docs/", SpectacularAPIView.as_view(urlconf="evibes.b2b_urls", custom_settings=SPECTACULAR_B2B_SETTINGS), @@ -17,7 +15,7 @@ urlpatterns = [ path(r"docs/swagger/", CustomSwaggerView.as_view(url_name="schema-b2b"), name="swagger-ui-b2b"), path(r"docs/redoc/", CustomRedocView.as_view(url_name="schema-b2b"), name="redoc-ui-b2b"), path(r"favicon.ico", favicon_view), - path(r"", include("core.b2b_urls")), + path(r"", include("core.b2b_urls", namespace="core_b2b")), ] if settings.DEBUG: diff --git a/payments/views.py b/payments/views.py index 9d3a1c6b..560b3481 100644 --- a/payments/views.py +++ b/payments/views.py @@ -16,6 +16,21 @@ logger = logging.getLogger(__name__) @extend_schema_view(**DEPOSIT_SCHEMA) class DepositView(APIView): + """Handles deposit operations. + + This class provides an API endpoint to handle deposit transactions. + It supports the creation of a deposit transaction after validating the + provided data. If the user is not authenticated, an appropriate response + is returned. On successful validation and execution, a response + with the transaction details is provided. + + Attributes: + No attributes are declared at the class-level for this view. + + Methods: + post: Processes the deposit request, validates the request data, ensures + user authentication, and creates a transaction. + """ def post(self, request, *args, **kwargs): logger.debug(request.__dict__) serializer = DepositSerializer(data=request.data) @@ -33,6 +48,23 @@ class DepositView(APIView): @extend_schema(exclude=True) class CallbackAPIView(APIView): + """ + Handles incoming callback requests to the API. + + This class processes and routes incoming HTTP POST requests to the appropriate + gateway handler based on the provided gateway parameter. It is designed to handle + callback events coming from external systems and provide an appropriate HTTP response + indicating success or failure. + + Attributes: + No additional attributes are defined for this class beyond what is + inherited from APIView. + + Methods: + post(request, *args, **kwargs): Processes POST requests and routes them + based on the specified gateway. Handles exceptions gracefully by returning + a server error response if an unknown gateway or other issues occur. + """ def post(self, request, *args, **kwargs): logger.debug(request.__dict__) try: diff --git a/payments/viewsets.py b/payments/viewsets.py index 0b7a141c..5ee92209 100644 --- a/payments/viewsets.py +++ b/payments/viewsets.py @@ -5,5 +5,20 @@ from payments.serializers import TransactionSerializer class TransactionViewSet(ReadOnlyModelViewSet): + """ + ViewSet for handling read-only operations on Transaction model. + + This class provides a read-only interface for interacting with transaction + data. It utilizes the TransactionSerializer for serializing and deserializing + the data. The class ensures that only authorized users, who meet specific + permissions, can access the transactions. + + Attributes: + serializer_class: Specifies the serializer class to be used for + serializing transaction data. + permission_classes: A tuple specifying the permissions required to access + the data. Includes custom permissions to restrict access based + on ownership and other criteria. + """ serializer_class = TransactionSerializer permission_classes = (EvibesPermission, IsOwner) diff --git a/vibes_auth/models.py b/vibes_auth/models.py index 797b1091..c512ebf1 100644 --- a/vibes_auth/models.py +++ b/vibes_auth/models.py @@ -30,6 +30,55 @@ from vibes_auth.validators import validate_phone_number class User(AbstractUser, NiceModel): + """ + Represents a User entity with customized fields and methods for extended functionality. + + This class extends the AbstractUser model and integrates additional features like + custom email login, validation methods, subscription status, verification, and + attributes storage. It also provides utilities for managing recently viewed items and + token-based activation for verifying accounts. The User model is designed to handle + specific use cases for enhanced user management. + + Attributes: + email: EmailField to store the user's email address. + phone_number: CharField for the user's phone number, allowing for optional storage and validation. + username: Has been set to None as email is the primary unique identifier. + first_name: Optional CharField for the user's first name. + last_name: Optional CharField for the user's last name. + avatar: ImageField for storing the path to the user's profile picture. + is_verified: BooleanField indicating whether the user's email has been verified. + is_active: BooleanField to toggle user activity without deleting the account. + is_subscribed: BooleanField indicating the user's newsletter subscription status. + activation_token: UUIDField for assigning a unique activation token to the user. + language: CharField storing the user's preferred language setting. + attributes: JSONField for custom storage of user-specific additional attributes. + USERNAME_FIELD: Specifies the unique identifier for the user (email in this case). + REQUIRED_FIELDS: A list of fields required when creating a user via createsuperuser, left empty here. + objects: Custom manager for User model providing additional methods for user creation. + payments_balance: Reference to the user's payment balance (related to external model). + user_related_wishlist: Reference to the user's wishlist (related to external model). + orders: QuerySet representing the user's associated orders. + + Methods: + add_to_recently_viewed(product_uuid): + Adds a product's UUID to the user's recently viewed items cache. Keeps a maximum + of 48 items and maintains their order of viewing. + + recently_viewed: (read-only property) + Retrieves a list of UUIDs representing the products recently viewed by the user + from the cache. + + check_token(token): + Validates the input token against the user's activation token. + + __str__(): + Returns the string representation of the user, which is the email address. + + Meta: + swappable: Configures the model to be replaceable with another user 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. + """ def get_uuid_as_path(self, *args): return str(self.uuid) + "/" + args[0] @@ -111,6 +160,19 @@ class User(AbstractUser, NiceModel): class Group(BaseGroup): + """ + Proxy model representing a Group entity. + + This class acts as a proxy for the `BaseGroup` model, providing additional + configuration for display and usage purposes. It does not introduce new fields + or behavior but alters representation and metadata for the Group model. + + Attributes: + Meta.proxy (bool): Indicates this is a proxy model. + Meta.verbose_name (str): Human-readable singular name for the Group model. + Meta.verbose_name_plural (str): Human-readable plural name for the Group + model. + """ class Meta: proxy = True verbose_name = _("group") @@ -118,6 +180,20 @@ class Group(BaseGroup): class OutstandingToken(BaseOutstandingToken): + """ + Represents a proxy model for outstanding tokens. + + This class is a proxy for the `BaseOutstandingToken` model, used to manage + and customize behaviors or configurations related to outstanding tokens. + It does not add additional fields or logic to the base model but allows for + overloading or extending its default functionality as required. + + Attributes: + Meta (class): Contains metadata for the model, including options such as + whether the model is a proxy, the human-readable name for the model, and + the plural form of that name. + + """ class Meta: proxy = True verbose_name = _("outstanding token") @@ -125,6 +201,19 @@ class OutstandingToken(BaseOutstandingToken): class BlacklistedToken(BaseBlacklistedToken): + """ + Represents a blacklisted token model in the system. + + This class acts as a Django model proxy and serves the purpose of managing + blacklisted tokens. It inherits from a base class provided for this purpose, + allowing for the extension of functionality or customization of behavior + without altering the original base class's structure. It also defines the + meta options for the model, affecting its database and administrative + representation. + + Attributes: + None + """ class Meta: proxy = True verbose_name = _("blacklisted token") diff --git a/vibes_auth/views.py b/vibes_auth/views.py index ef12276d..3a8dffe7 100644 --- a/vibes_auth/views.py +++ b/vibes_auth/views.py @@ -24,6 +24,28 @@ logger = logging.getLogger(__name__) @extend_schema_view(**TOKEN_OBTAIN_SCHEMA) class TokenObtainPairView(TokenViewBase): + """ + Represents a view for obtaining a pair of access and refresh tokens. + + This view manages the process of handling token-based authentication where + clients can obtain a pair of JWT tokens (access and refresh) using provided + credentials. It is built on top of a base token view and ensures proper + rate limiting to protect against brute force attacks. + + Attributes: + serializer_class: Serializer class used for processing request data + and returning response data. + _serializer_class: Internal serializer class reference. + + Usage: + This view should be used in authentication-related APIs where clients + need to obtain new sets of tokens. It incorporates both a serializer for + processing incoming data and also rate limiting to enforce request limits. + + Methods: + post: Handles HTTP POST requests for token retrieval. This method is + subject to rate limiting depending on the global DEBUG setting. + """ serializer_class = TokenObtainPairSerializer # type: ignore _serializer_class = TokenObtainPairSerializer # type: ignore @@ -34,6 +56,30 @@ class TokenObtainPairView(TokenViewBase): @extend_schema_view(**TOKEN_REFRESH_SCHEMA) class TokenRefreshView(TokenViewBase): + """ + Handles refreshing of tokens for authentication purposes. + + This class is used to provide functionality for token refresh + operations as part of an authentication system. It ensures that + clients can request a refreshed token within defined rate limits. + The view relies on the associated serializer to validate token + refresh inputs and produce appropriate outputs. + + Attributes: + serializer_class (Serializer): The serializer used to handle + token refresh operations. This establishes the validation + and processing logic for incoming requests. + + _serializer_class (Serializer): Internal reference to the + serializer, typically used for ensuring consistent processing + for refresh-related logic. + + Methods: + post: Handles HTTP POST requests to refresh the token. + Rate limits requests based on the IP of the client submitting + the request. Rate limit settings are defined depending on + whether the application is in DEBUG mode or not. + """ serializer_class = TokenRefreshSerializer # type: ignore _serializer_class = TokenRefreshSerializer # type: ignore @@ -44,6 +90,17 @@ class TokenRefreshView(TokenViewBase): @extend_schema_view(**TOKEN_VERIFY_SCHEMA) class TokenVerifyView(TokenViewBase): + """ + Represents a view for verifying JSON Web Tokens (JWT) using specific serialization + and validation logic. + + This class inherits from the `TokenViewBase` and is designed to handle the POST + request for verifying JWT tokens. Tokens are validated using the associated + `TokenVerifySerializer`. The view processes incoming requests, validates tokens, + and returns a response indicating whether the token is valid. If valid, associated + user data can also be returned. Errors during token validation result in an appropriate + error response. + """ serializer_class = TokenVerifySerializer # type: ignore _serializer_class = TokenVerifySerializer # type: ignore diff --git a/vibes_auth/viewsets.py b/vibes_auth/viewsets.py index eafb2c34..a6c629a5 100644 --- a/vibes_auth/viewsets.py +++ b/vibes_auth/viewsets.py @@ -38,6 +38,46 @@ class UserViewSet( mixins.DestroyModelMixin, GenericViewSet, ): + """ + User view set implementation using Django REST framework. + + Provides a set of actions that manage user-related data such as creation, + retrieval, updates, deletion, and custom actions including password reset, + avatar upload, account activation, and recently viewed items merging. + This class extends the mixins and GenericViewSet for robust API handling. + + Attributes: + serializer_class (class): Serializer class used to serialize the user data. + queryset (QuerySet): Queryset that fetches active user objects. + permission_classes (list): List of permissions applied to certain actions. + + Methods: + reset_password(request): + Sends a reset password email to a user based on the provided email. + upload_avatar(request, **_kwargs): + Allows an authenticated user to upload an avatar for their profile. + confirm_password_reset(request, *_args, **_kwargs): + Confirms the password reset and updates the new password for a user. + create(request, *args, **kwargs): + Creates a new user instance using the provided payload. + activate(request): + Activates a user account based on their unique activation link. + merge_recently_viewed(request, **_kwargs): + Merges a list of recently viewed products into the user's profile. + retrieve(request, pk=None, *args, **kwargs): + Retrieves user details for the given user ID. + update(request, pk=None, *args, **kwargs): + Updates user details for the given user ID. + + Raises: + DoesNotExist: + Raised when a user is not found in specific methods working with + database queries. + ValidationError: + Raised for invalid data during serialization or password validation. + OverflowError, TypeError: + Raised for decoding or type conversion issues. + """ serializer_class = UserSerializer queryset = User.objects.filter(is_active=True) permission_classes = [AllowAny]