From 7dc69ad63f8d520e957838468fbbf6968fa4365e Mon Sep 17 00:00:00 2001 From: Egor fureunoir Gorbunov Date: Sun, 29 Jun 2025 19:12:48 +0300 Subject: [PATCH] Features: 1) Add `docutils` dependency to `pyproject.toml` and `poetry.lock` for enhanced documentation utilities; 2) Add verbose and descriptive docstrings for multiple `core` models to outline attributes, methods, and meta options; 3) Enable `XViewMiddleware` in settings for admin documentation support; Fixes: None; Extra: Update `lock-version` and `content-hash` in `poetry.lock` reflecting the addition of `docutils` package; --- core/models.py | 482 ++++++++++++++++++++++++++++++++++++++++ evibes/settings/base.py | 1 + poetry.lock | 13 +- pyproject.toml | 1 + 4 files changed, 496 insertions(+), 1 deletion(-) diff --git a/core/models.py b/core/models.py index 96fb0b5c..ef2832da 100644 --- a/core/models.py +++ b/core/models.py @@ -60,6 +60,29 @@ logger = logging.getLogger(__name__) class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel): + """ + Represents a group of attributes, which can be hierarchical. + + This class is used to manage and organize attribute groups. An attribute + group can have a parent group, forming a hierarchical structure. This can + be useful for categorizing and managing attributes more effectively in a + complex system. + + Attributes: + parent (Self): A foreign key referencing the parent of this group. It + can be null or blank if the group does not have a parent. The parent + group organizes the hierarchical structure. + name (str): The unique name of the attribute group. It is limited to a + maximum of 255 characters. + is_publicly_visible (bool): Indicates if the attribute group is visible + publicly. + + Meta: + verbose_name: A human-readable name for the class, set to 'attribute + group'. + verbose_name_plural: A human-readable plural name for the class, set to + 'attribute groups'. + """ is_publicly_visible = True parent: Self = ForeignKey( # type: ignore @@ -87,6 +110,33 @@ class AttributeGroup(ExportModelOperationsMixin("attribute_group"), NiceModel): class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): + """ + Represents a vendor entity capable of storing information about external vendors and + their interaction requirements. + + The Vendor class is used to define and manage information related to an external vendor. + It stores the vendor's name, authentication details required for communication, + and the percentage markup applied to products retrieved from the vendor. This model also + maintains additional metadata and constraints, making it suitable for use in systems + that interact with third-party vendors. + + Attributes: + authentication (dict): Credentials and endpoint information required for vendor + communication, stored in a JSON field. + markup_percent (int): The markup percentage applied to products sent by this + vendor. Must be an integer between 0 and 100 inclusive. + name (str): The unique name of the vendor, with a maximum length of 255 + characters. + + Meta: + verbose_name (str): Singular name of the vendor entity ("vendor"). + verbose_name_plural (str): Plural name of the vendor entities ("vendors"). + indexes (list): List of database indexes applied to this model, including a + GIN index on the 'authentication' field. + + Returns: + str: The vendor's name when the instance is represented as a string. + """ is_publicly_visible = False authentication: dict = JSONField( # type: ignore @@ -122,6 +172,21 @@ class Vendor(ExportModelOperationsMixin("vendor"), NiceModel): class ProductTag(ExportModelOperationsMixin("product_tag"), NiceModel): + """ + Represents a product tag used for classifying or identifying products. + + The ProductTag class is designed to uniquely identify and classify products + through a combination of an internal tag identifier and a user-friendly + display name. It supports operations exported through mixins and provides + metadata customization for administrative purposes. + + Attributes: + is_publicly_visible: A boolean indicating whether the tag is publicly + visible. + tag_name: Internal tag identifier for the product tag. + name: User-friendly name for the product tag. + + """ is_publicly_visible = True tag_name: str = CharField( # type: ignore @@ -147,6 +212,18 @@ class ProductTag(ExportModelOperationsMixin("product_tag"), NiceModel): class CategoryTag(ExportModelOperationsMixin("category_tag"), NiceModel): + """ + Represents a category tag used for products. + + This class models a category tag that can be used to associate and classify products. + It includes attributes for an internal tag identifier and a user-friendly display name. + + Attributes: + is_publicly_visible (bool): Indicates if the category tag is publicly visible. + tag_name (str): Internal tag identifier for the product tag. + name (str): User-friendly name for the product tag. + + """ is_publicly_visible = True tag_name: str = CharField( # type: ignore @@ -172,6 +249,73 @@ class CategoryTag(ExportModelOperationsMixin("category_tag"), NiceModel): class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): + """ + Represents a category entity to organize and group related items in a hierarchical + structure. Categories may have hierarchical relationships with other categories, + supporting parent-child relationships. The class includes fields for metadata and + visual representation, which serve as a foundation for category-related features. + + This class is typically used to define and manage product categories or other similar + groupings within an application, allowing users or administrators to specify the + name, description, and hierarchy of categories, as well as assign attributes like + images, tags, or priority. + + Attributes + ---------- + is_publicly_visible : bool + A flag indicating whether the category is visible to the public. + + image : ImageField + Represents an optional image associated with the category. The image is used + to visually represent the category. + + markup_percent : int + Specifies the markup percentage for products in this category. It is validated + to ensure values fall between 0 and 100. + + parent : Self + Represents the parent category in a hierarchical structure. This forms category + relationships to enable nesting. + + name : str + The name of the category, which also must be unique. This serves as the primary + identifier for the category. + + description : str + An optional detailed description explaining the purpose or details of the category. + + slug : str + A unique, auto-generated field created from the category's name and parent name, + suitable for use in URLs and identifying the category. + + tags : CategoryTag + Optional tags used to group or describe the category better. + + priority : int + Represents the priority of the category, which could be used for sorting or + rendering purposes. + + Methods + ------- + __str__() + Returns the name of the category as its string representation. + + get_tree_depth() + Computes the depth of the category in the hierarchical structure. It determines + the maximum depth of its descendants or returns zero if the category is a leaf. + + Meta Options + ------------ + verbose_name : str + Specifies the singular human-readable name for the category model. + + verbose_name_plural : str + Specifies the plural human-readable name for the category model. + + ordering : list + Defines the default ordering for category instances, based on their hierarchical + structure. + """ is_publicly_visible = True image = ImageField( # type: ignore @@ -254,6 +398,24 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): class Brand(ExportModelOperationsMixin("brand"), NiceModel): + """ + Represents a Brand object in the system. + + This class handles information and attributes related to a brand, including its name, logos, + description, associated categories, a unique slug, and priority order. + It allows for the organization and representation of brand-related data within the application. + + Attributes: + is_publicly_visible (bool): Indicates if the brand is visible publicly. + name (str): The name of the brand. + small_logo (ImageField): An optional small logo image file representing the brand. + big_logo (ImageField): An optional large logo image file representing the brand. + description (str): An optional textual description providing details about the brand. + categories (Category): Optional categories associated with this brand. + slug (str): A unique auto-generated slug used for SEO-friendly URLs. + priority (int): Specifies the priority ranking of the brand. + + """ is_publicly_visible = True name: str = CharField( # type: ignore @@ -317,6 +479,40 @@ class Brand(ExportModelOperationsMixin("brand"), NiceModel): class Product(ExportModelOperationsMixin("product"), NiceModel): + """ + Represents a product with attributes such as category, brand, tags, digital status, name, + description, part number, and slug. Provides related utility properties to retrieve + ratings, feedback counts, price, quantity, and total orders. Designed for use in a + system that handles e-commerce or inventory management. + + This class interacts with related models (such as Category, Brand, and ProductTag) and + manages caching for frequently accessed properties to improve performance. It is used + to define and manipulate product data and its associated information within + an application. + + Attributes: + is_publicly_visible (bool): Indicates whether the product is visible to the public. + category (Category): The category this product belongs to. + brand (Brand, optional): Optionally associates this product with a brand. + tags (ProductTag): Tags that help describe or group this product. + is_digital (bool): Indicates whether this product is digitally delivered. + name (str): The identifying name for the product. + description (str, optional): A detailed description of the product. + partnumber (str): The unique part number for this product. + slug (str, optional): Auto-generated unique slug for the product. + + Meta: + verbose_name (str): The singular name of the product model. + verbose_name_plural (str): The plural name of the product model. + + Properties: + rating (float): The average rating of the product, rounded to 2 decimal places. + feedbacks_count (int): The total number of feedback entries associated with the product. + price (float): The lowest price of the product based on its stock, rounded to 2 decimal + places. + quantity (int): The total available quantity of the product across all its stocks. + total_orders (int): Counts the total orders made for the product in relevant statuses. + """ is_publicly_visible = True category: Category = ForeignKey( # type: ignore @@ -439,6 +635,31 @@ class Product(ExportModelOperationsMixin("product"), NiceModel): class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): + """ + Represents an attribute in the system. + + This class is used to define and manage attributes, which are customizable + pieces of data that can be associated with other entities. Attributes + have associated categories, groups, value types, and names. The model + supports multiple types of values, including string, integer, float, + boolean, array, and object. This allows for dynamic and flexible data + structuring. + + Attributes: + is_publicly_visible (bool): Denotes whether the attribute is publicly + visible. Defaults to True. + + categories (ManyToManyField): Categories to which this attribute + belongs. It is a many-to-many relationship with `Category` model. + + group (ForeignKey): The group to which this attribute belongs. It is + a ForeignKey relation to the `AttributeGroup` model. + + value_type (CharField): The type of the attribute's value. Options + include string, integer, float, boolean, array, or object. + + name (CharField): The unique name of the attribute. + """ is_publicly_visible = True categories: Category = ManyToManyField( # type: ignore @@ -485,6 +706,28 @@ class Attribute(ExportModelOperationsMixin("attribute"), NiceModel): class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel): + """ + Represents a specific value for an attribute that is linked to a product. + + This class serves the purpose of mapping a value to an attribute for a + specific product. It links the 'attribute' to a unique 'value', allowing + better organization and dynamic representation of product characteristics. + It also defines whether the attribute value is public through the + 'is_publicly_visible' attribute. + + Attributes + ---------- + is_publicly_visible : bool + Determines if the attribute value is visible publicly. Defaults to True. + attribute : core.Attribute + The 'Attribute' object this value is linked to. Foreign key relationship + with 'core.Attribute'. + product : core.Product + The specific 'Product' this attribute's value is associated with. + Foreign key relationship with 'core.Product'. + value : str + Holds the specific value for this attribute as a text field. + """ is_publicly_visible = True attribute: Attribute = ForeignKey( # type: ignore @@ -517,6 +760,23 @@ class AttributeValue(ExportModelOperationsMixin("attribute_value"), NiceModel): class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): + """ + Represents a product image associated with a product in the system. + + This class is designed to manage images for products, including functionality + for uploading image files, associating them with specific products, and + determining their display order. It also includes an accessibility feature + with alternative text for the images. + + Attributes: + is_publicly_visible (bool): A flag indicating whether the image is + visible publicly. + alt (str): Alternative text for the image to support accessibility. + image (ImageField): The image file associated with the product. + priority (int): The display priority of the image. Images with lower + priority values are displayed first. + product (ForeignKey): The product to which this image is associated. + """ is_publicly_visible = True alt: str = CharField( # type: ignore @@ -556,6 +816,38 @@ class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): class Promotion(ExportModelOperationsMixin("promotion"), NiceModel): + """ + Represents a promotional campaign for products with a discount. + + This class is used to define and manage promotional campaigns that offer a + percentage-based discount for products. The class includes attributes for + setting the discount rate, providing details about the promotion, and linking + it to the applicable products. It integrates with the product catalog to + determine the affected items in the campaign. + + Attributes: + is_publicly_visible: A class-level attribute indicating whether the promotion + is publicly visible. + discount_percent: IntegerField. Specifies the percentage discount for the + selected products. Must be between 1 and 100 inclusive. + name: CharField. A unique name for the promotion, required for promoting + distinguishable campaigns. Maximum length is 256 characters. + description: TextField, optional. Provides a detailed description of the + promotion. Can be left blank or null. + products: ManyToManyField. Links the promotion to the products that are included + in its scope. Can be left blank. + + Meta: + verbose_name: The singular name for the promotion in database and UI contexts. + verbose_name_plural: The pluralized name for multiple promotions in database and + UI contexts. + + Methods: + __str__(): + Returns a string representation of the promotion. If the name is + provided, it returns the name; otherwise, it returns the ID of the + promotion as a string. + """ is_publicly_visible = True discount_percent: int = IntegerField( # type: ignore @@ -593,6 +885,25 @@ class Promotion(ExportModelOperationsMixin("promotion"), NiceModel): class Stock(ExportModelOperationsMixin("stock"), NiceModel): + """ + Represents the stock of a product managed in the system. + + This class provides details about the relationship between vendors, products, + and their stock information, as well as inventory-related properties like price, + purchase price, quantity, SKU, and digital assets. It is part of the inventory + management system to allow tracking and evaluation of products available from + various vendors. + + Attributes: + is_publicly_visible (bool): Indicates if the stock is publicly visible. Defaults to False. + vendor (ForeignKey): The vendor supplying this product stock. + price (float): The final price to the customer after markups. + product (ForeignKey): The product associated with this stock entry. + purchase_price (float): The price paid to the vendor for this product. + quantity (int): Available quantity of the product in stock. + sku (str): Vendor-assigned SKU for identifying the product. + digital_asset (FileField): Digital file associated with this stock if applicable. + """ is_publicly_visible = False vendor: ForeignKey = ForeignKey( @@ -648,6 +959,15 @@ class Stock(ExportModelOperationsMixin("stock"), NiceModel): class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): + """ + Represents a user's wishlist for storing and managing desired products. + + The Wishlist class provides functionality to manage a collection of products + that a user wishes to save. It supports operations such as adding products, + removing products, adding multiple products in bulk, and removing multiple + products in bulk. The wishlist is associated with a specific user and is + stored with optional public visibility status. + """ is_publicly_visible = False products: ManyToManyField = ManyToManyField( # type: ignore @@ -709,6 +1029,25 @@ class Wishlist(ExportModelOperationsMixin("wishlist"), NiceModel): class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel): + """ + Model representing a documentary record tied to a product. + + This class is used to store information about documentaries related to specific + products, including file uploads and their metadata. It contains methods and + properties to handle the file type and storage path for the documentary files. + It extends functionality from specific mixins and provides additional custom + features. + + Attributes: + is_publicly_visible: A boolean indicating if the documentary is + publicly visible. + product: ForeignKey linking the documentary to a product. + document: FileField used to store the file associated with the documentary. + + Meta: + verbose_name: Singular name for the documentary model. + verbose_name_plural: Plural name for the documentary model. + """ is_publicly_visible = True product: ForeignKey = ForeignKey(to=Product, on_delete=CASCADE, related_name="documentaries") @@ -730,6 +1069,42 @@ class Documentary(ExportModelOperationsMixin("attribute_group"), NiceModel): class Address(ExportModelOperationsMixin("address"), NiceModel): + """ + Represents an address entity that includes location details and associations with + a user. Provides functionality for geographic and address data storage, as well + as integration with geocoding services. + + This class is designed to store detailed address information including components + like street, city, region, country, and geolocation (longitude and latitude). + + It supports integration with geocoding APIs, enabling the storage of raw API + responses for further processing or inspection. The class also allows associating + an address with a user, facilitating personalized data handling. + + Attributes: + is_publicly_visible (bool): Indicates whether the address is visible publicly. + address_line (str): A general address line containing information about the + customer's location. Optional. + street (str): The street name or number in the address. Optional. + district (str): The district related to the address. Optional. + city (str): The name of the city where the address is located. Optional. + region (str): The name of the region associated with the address. Optional. + postal_code (str): The postal code corresponding to the address. Optional. + country (str): The country where the address resides. Optional. + location (PointField): A geolocation represented as (longitude, latitude). + Allows geospatial searches. Optional. + raw_data (dict): The full JSON response directly from the geocoding service, + containing detailed information about the address. Optional. + api_response (dict): Stores a processed version or subset of the JSON + response from the geocoding service. Optional. + user (ForeignKey): Reference to a User entity who owns this address. Optional. + + Meta: + verbose_name (str): Human-readable singular name for the address. + verbose_name_plural (str): Human-readable plural name for addresses. + indexes (list): Database indexes defined for improving query performance + on specific fields like 'location'. + """ is_publicly_visible = False address_line: str = TextField( # type: ignore @@ -778,6 +1153,33 @@ class Address(ExportModelOperationsMixin("address"), NiceModel): class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): + """ + Represents a promotional code that can be used for discounts, managing its validity, + type of discount, and application. + + The PromoCode class stores details about a promotional code, including its unique + identifier, discount properties (amount or percentage), validity period, associated + user (if any), and status of its usage. It includes functionality to validate and + apply the promo code to an order while ensuring constraints are met. + + Attributes: + code (str): The unique identifier for the promo code. + discount_amount (Decimal): The fixed discount amount applied, if defined. + discount_percent (int): The percentage discount applied, if defined. + end_time (datetime): The expiration timestamp of the promo code. + start_time (datetime): The timestamp from when the promo code is valid. + used_on (datetime): The timestamp when the promo code was used (if applicable). + user (ForeignKey): The user associated with the promo code, if any. + + Methods: + save(**kwargs): Ensures only one type of discount (amount or percent) is defined. + __str__(): Returns the promo code identifier as its string representation. + use(order): Applies the promo code to the given order and calculates final price. + + Meta: + verbose_name: Display name for the promo code model. + verbose_name_plural: Plural display name for the promo code model. + """ is_publicly_visible = False code: str = CharField( # type: ignore @@ -875,6 +1277,25 @@ class PromoCode(ExportModelOperationsMixin("promocode"), NiceModel): class Order(ExportModelOperationsMixin("order"), NiceModel): + """ + Represents an order placed by a user. + + This class models an order within the application, including its various attributes such as billing + and shipping information, status, associated user, notifications, and related operations. + Orders can have associated products, promotions can be applied, addresses set, and shipping or billing + details updated. Equally, functionality supports managing the products in the order lifecycle. + + Attributes: + billing_address (Address): The billing address used for the order. + promo_code (PromoCode): An optional promo code applied to the order. + shipping_address (Address): The shipping address used for the order. + status (str): The current status of the order (e.g., PENDING, COMPLETED). + notifications (dict): JSON structure dictating notifications for the user. + attributes (dict): JSON representation of additional order-specific attributes. + user (User): The user who placed the order. + buy_time (datetime): Timestamp when the order was finalized. + human_readable_id (str): A unique human-readable identifier for the order. + """ is_publicly_visible = False billing_address: Address = ForeignKey( # type: ignore @@ -1264,6 +1685,28 @@ class Order(ExportModelOperationsMixin("order"), NiceModel): class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): + """ + Represents a product associated with an order. + + The OrderProduct model maintains information about a product that is part of an order, + including details such as purchase price, quantity, product attributes, and status. It + manages notifications for the user and administrators and handles operations such as + returning the product balance or adding feedback. This model also provides methods and + properties that support business logic, such as calculating the total price or generating + a download URL for digital products. The model integrates with the Order and Product models + and stores a reference to them. + + Attributes: + is_publicly_visible (bool): Indicates whether this model is visible publicly. + buy_price (float): The price paid by the customer for this product at purchase time. + comments (str): Internal comments entered by admins regarding this ordered product. + notifications (dict): JSON structure containing notifications relevant to the product. + attributes (dict): JSON representation of the product's attributes as part of the order. + order (Order): Reference to the parent order that contains this product. + product (Product): Reference to the specific product associated with the order line. + quantity (int): Represents the quantity of this product ordered. + status (str): The current status of the product in the order. + """ is_publicly_visible = False buy_price: float = FloatField( # type: ignore @@ -1388,6 +1831,29 @@ class OrderProduct(ExportModelOperationsMixin("order_product"), NiceModel): class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceModel): + """ + Represents the downloading functionality for digital assets associated + with orders. + + The DigitalAssetDownload class provides the ability to manage and access + downloads related to order products. It maintains information about the + associated order product, the number of downloads, and whether the asset + is publicly visible. It includes a method to generate a URL for downloading + the asset when the associated order is in a completed status. + + Attributes: + is_publicly_visible (bool): Indicates whether the digital asset is + publicly visible. Always set to False for this class. + order_product (OneToOneField): Reference to the associated order product. + It has a one-to-one relationship with the OrderProduct model, and + deleting the OrderProduct will delete the associated download. + num_downloads (int): Indicates the number of times the digital asset + has been downloaded. + + Methods: + url: Property to generate the download URL for the digital asset + if the associated order is in a finished status. + """ is_publicly_visible = False order_product: OneToOneField = OneToOneField(to=OrderProduct, on_delete=CASCADE, related_name="download") # type: ignore @@ -1411,6 +1877,22 @@ class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceMo class Feedback(ExportModelOperationsMixin("feedback"), NiceModel): + """ + Manages user feedback for products. + + This class is designed to capture and store user feedback for specific products + that they have purchased. It contains attributes to store user comments, + a reference to the related product in the order, and a user-assigned rating. The + class utilizes database fields to effectively model and manage feedback data. + + Attributes: + is_publicly_visible (bool): Indicates whether the feedback is visible to the public. + comment (str): User-provided comments about their experience with the product. + order_product (OrderProduct): Reference to the specific product in an order that this + feedback is about. + rating (float): User-assigned rating for the product, validated to be within the range + of 0 to 10. + """ is_publicly_visible = True comment: str = TextField( # type: ignore diff --git a/evibes/settings/base.py b/evibes/settings/base.py index 9229466a..d03f904c 100644 --- a/evibes/settings/base.py +++ b/evibes/settings/base.py @@ -153,6 +153,7 @@ MIDDLEWARE: list[str] = [ "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", + "django.contrib.admindocs.middleware.XViewMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "evibes.middleware.CustomLocaleMiddleware", "django_hosts.middleware.HostsResponseMiddleware", diff --git a/poetry.lock b/poetry.lock index 03fd1416..ae106660 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1644,6 +1644,17 @@ dev = ["Django (>=1.6)", "djangorestframework (>=2.4.3)", "flake8", "mkdocs (>=0 docs = ["mkdocs (>=0.11.1)"] tests = ["Django (>=1.6)", "djangorestframework (>=2.4.3)", "flake8", "pytest", "pytest-django"] +[[package]] +name = "docutils" +version = "0.21.2" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.9" +files = [ + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, +] + [[package]] name = "drf-spectacular" version = "0.28.0" @@ -5125,4 +5136,4 @@ worker = ["celery", "celery-prometheus-exporter", "django-celery-beat", "django- [metadata] lock-version = "2.0" python-versions = ">=3.12,<3.13" -content-hash = "589469959dc87190309385f2a6eaf96305c0f51682d26e4535206994594ae0da" +content-hash = "58d67f7b6c2313bdb117965a9c9555319bbb059db043e5723d39a27c36695939" diff --git a/pyproject.toml b/pyproject.toml index 1385a0f4..1d362f5d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,7 @@ djangorestframework-simplejwt = { extras = ["crypto"], version = "5.5.0" } djangorestframework-stubs = "3.16.0" djangorestframework-xml = "2.0.0" djangorestframework-yaml = "2.0.0" +docutils = "0.21.2" drf-spectacular = { extras = ["sidecar"], version = "0.28.0" } elasticsearch = "8.18.1" elasticsearch-dsl = "8.18.0"