From dc1e79c6844ed76f2fa1e0c21f6cb3fa1c8fa1c8 Mon Sep 17 00:00:00 2001 From: Mojtaba-z Date: Sat, 19 Jul 2025 10:41:03 +0330 Subject: [PATCH] celery & attributes list by product --- Rasaddam_Backend/__init__.py | 4 ++ Rasaddam_Backend/celery.py | 44 +++++++++++++++++++ Rasaddam_Backend/settings.py | 15 ++++++- apps/authentication/tasks.py | 12 +++++ apps/core/models.py | 12 ++--- .../quota_distribution_serializers.py | 1 + .../web/api/v1/viewsets/product_api.py | 17 ++++++- 7 files changed, 97 insertions(+), 8 deletions(-) create mode 100644 Rasaddam_Backend/celery.py create mode 100644 apps/authentication/tasks.py diff --git a/Rasaddam_Backend/__init__.py b/Rasaddam_Backend/__init__.py index e69de29..e0b971e 100644 --- a/Rasaddam_Backend/__init__.py +++ b/Rasaddam_Backend/__init__.py @@ -0,0 +1,4 @@ +from __future__ import absolute_import, unicode_literals +from .celery import app as celery_app + +__all__ = ('celery_app',) \ No newline at end of file diff --git a/Rasaddam_Backend/celery.py b/Rasaddam_Backend/celery.py new file mode 100644 index 0000000..f055103 --- /dev/null +++ b/Rasaddam_Backend/celery.py @@ -0,0 +1,44 @@ +from __future__ import absolute_import, unicode_literals +import os +from celery.schedules import crontab +from celery import Celery +import django +from django.conf import settings + +# Set the default Django settings module for the 'celery' program. +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Rasaddam_Backend.settings") + +django.setup() + +app = Celery("Rasaddam_Backend") + +# Using a string here means the worker doesn't have to serialize +# the configuration object to child processes. +# - namespace='CELERY' means all celery-related configuration keys +# should have a `CELERY_` prefix. +app.config_from_object("django.conf:settings", namespace="CELERY") + +""" +celery beat conf +""" +app.conf.beat_schedule = {} + +# Load task modules from all registered Django apps. +app.autodiscover_tasks() + + +@app.task(bind=True, ignore_result=True) +def debug_task(self): + print(f"Request: {self.request!r}") + + +""" +celery beat conf +""" +app.conf.beat_schedule = { + 'add-every-30-seconds': { + 'task': 'apps.authentication.tasks.task_func', + 'schedule': 5.0, + # 'args': (16, 16), + }, +} diff --git a/Rasaddam_Backend/settings.py b/Rasaddam_Backend/settings.py index 852681b..aec1d3c 100644 --- a/Rasaddam_Backend/settings.py +++ b/Rasaddam_Backend/settings.py @@ -86,7 +86,9 @@ INSTALLED_APPS = [ 'apps.product.apps.ProductConfig', 'rest_captcha', 'captcha', - 'drf_yasg' + 'drf_yasg', + "django_celery_results", + "django_celery_beat", ] MIDDLEWARE = [ @@ -162,6 +164,17 @@ SWAGGER_SETTINGS = { "DEFAULT_AUTO_SCHEMA_CLASS": "drf_yasg.inspectors.SwaggerAutoSchema" } +CELERY_BROKER_URL = "redis://:ydnW4hwzuDRYcTX3FWCHgQ1f@apo.liara.cloud:33740/0" # Requires Redis server +accept_content = ["application/json"] +result_serializer = "json" +task_serializer = "json" +timezone = "UTC" +CELERY_RESULT_BACKEND = "redis://:ydnW4hwzuDRYcTX3FWCHgQ1f@apo.liara.cloud:33740/0" +CELERY_CACHE_BACKEND = 'default' + +# Celery Beat settings +CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler" + LOGIN_URL = 'rest_framework:login' LOGOUT_URL = 'rest_framework:logout' diff --git a/apps/authentication/tasks.py b/apps/authentication/tasks.py new file mode 100644 index 0000000..8be0274 --- /dev/null +++ b/apps/authentication/tasks.py @@ -0,0 +1,12 @@ +from celery import shared_task +from apps.product.models import SaleUnit + + +@shared_task(bind=True) +def task_func(self): + print("sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss") + sale_unit = SaleUnit.objects.get(id=1) + print(sale_unit.unit) + sale_unit.trash = True + sale_unit.save() + return 'Done' diff --git a/apps/core/models.py b/apps/core/models.py index 3b1c341..cf073b5 100644 --- a/apps/core/models.py +++ b/apps/core/models.py @@ -28,12 +28,12 @@ class BaseModel(models.Model): abstract = True def save(self, *args, **kwargs): - user = get_current_user() # get user object - self.modified_by = user - if not self.creator_info: - self.created_by = user - self.creator_info = user.first_name + ' ' + user.last_name - self.modifier_info = user.first_name + ' ' + user.last_name + # user = get_current_user() # get user object + # self.modified_by = user + # if not self.creator_info: + # self.created_by = user + # self.creator_info = user.first_name + ' ' + user.last_name + # self.modifier_info = user.first_name + ' ' + user.last_name super(BaseModel, self).save(*args, **kwargs) diff --git a/apps/product/web/api/v1/serializers/quota_distribution_serializers.py b/apps/product/web/api/v1/serializers/quota_distribution_serializers.py index 43a3fb7..b1f00fe 100644 --- a/apps/product/web/api/v1/serializers/quota_distribution_serializers.py +++ b/apps/product/web/api/v1/serializers/quota_distribution_serializers.py @@ -42,6 +42,7 @@ class QuotaDistributionSerializer(serializers.ModelSerializer): if quota.is_closed: raise QuotaClosedException() + # check if assigned organization is in quota limitation if assigned_organization not in quota.limit_by_organizations.all(): raise QuotaLimitByOrganizationException() diff --git a/apps/product/web/api/v1/viewsets/product_api.py b/apps/product/web/api/v1/viewsets/product_api.py index 64c26a9..174fcae 100644 --- a/apps/product/web/api/v1/viewsets/product_api.py +++ b/apps/product/web/api/v1/viewsets/product_api.py @@ -118,11 +118,26 @@ class ProductViewSet(viewsets.ModelViewSet): class AttributeViewSet(viewsets.ModelViewSet): """ attributes of reference product """ # - queryset = product_models.Attribute.objects.all() + queryset = product_models.Attribute.objects.select_related('product').all() serializer_class = product_serializers.AttributeSerializer filter_backends = [filters.SearchFilter] search_fields = ['name'] + @action( + methods=['get'], + detail=True, + url_path='by_product', + url_name='by_product', + name='by_product' + ) + def get_attributes_by_product(self, request, pk=None): + """ get attributes by product with global ones """ + + attributes = self.queryset.filter(Q(is_global=True) | Q(product__id=pk)) + + serializer = self.serializer_class(attributes, many=True) + return Response(serializer.data) + @action( methods=['put'], detail=True,