diff --git a/.env.sample b/.env.sample index cc401799..c6e40a83 100644 --- a/.env.sample +++ b/.env.sample @@ -43,4 +43,12 @@ LAUNCHPAD_ADMIN_EMAIL = DISCORD_CLIENT_ID=xxx DISCORD_CLIENT_SECRET=xxx DISCORD_GUILD_ID=xxx -DISCORD_BOT_TOKEN=xxx \ No newline at end of file +DISCORD_BOT_TOKEN=xxx + +AWS_STORAGE_BUCKET_NAME = +AWS_S3_ACCESS_KEY_ID = +AWS_S3_SECRET_ACCESS_KEY = + +MEDIAFILES_LOCATION = dev/media +STATICFILES_LOCATION = dev/static +PUBLIC_STORAGE_LOCATION = dev/public \ No newline at end of file diff --git a/api/dashboard/ig/dash_ig_serializer.py b/api/dashboard/ig/dash_ig_serializer.py index 6b254f4e..dfad4377 100644 --- a/api/dashboard/ig/dash_ig_serializer.py +++ b/api/dashboard/ig/dash_ig_serializer.py @@ -1,4 +1,3 @@ - from rest_framework import serializers from db.task import InterestGroup @@ -6,10 +5,26 @@ class InterestGroupSerializer(serializers.ModelSerializer): - updated_by = serializers.CharField(source='updated_by.full_name') - created_by = serializers.CharField(source='created_by.full_name') members = serializers.SerializerMethodField() - category = serializers.ChoiceField(choices=["hardware", "coder", "creative", "manager", "others"]) + category = serializers.ChoiceField( + choices=["hardware", "coder", "creative", "manager", "others"] + ) + logo = serializers.SerializerMethodField() + + def get_logo(self, obj): + return ( + { + "original": obj.logo.url, + "thumbnail": obj.logo.thumbnail.url, + "medium": obj.logo.medium.url, + } + if obj.logo + else None + ) + + def get_members(self, obj): + return obj.user_ig_link_ig.all().count() + class Meta: model = InterestGroup fields = [ @@ -19,15 +34,55 @@ class Meta: "code", "category", "members", - "updated_by", - "updated_at", - "created_by", + "short_description", + "logo", "created_at", ] + +class InterestGroupDetailSerializer(serializers.ModelSerializer): + + updated_by = serializers.CharField(source="updated_by.full_name") + created_by = serializers.CharField(source="created_by.full_name") + members = serializers.SerializerMethodField() + category = serializers.ChoiceField( + choices=["hardware", "coder", "creative", "manager", "others"] + ) + logo = serializers.SerializerMethodField() + + def get_logo(self, obj): + return ( + { + "original": obj.logo.url, + "thumbnail": obj.logo.thumbnail.url, + "medium": obj.logo.medium.url, + } + if obj.logo + else None + ) + def get_members(self, obj): return obj.user_ig_link_ig.all().count() + class Meta: + model = InterestGroup + fields = [ + "id", + "name", + "icon", + "code", + "category", + "members", + "short_description", + "about", + "logo", + "cover_image", + "updated_by", + "updated_at", + "created_by", + "created_at", + ] + class InterestGroupCreateUpdateSerializer(serializers.ModelSerializer): @@ -38,6 +93,10 @@ class Meta: "code", "category", "icon", + "logo", + "cover_image", + "about", + "short_description", "created_by", - "updated_by" + "updated_by", ] diff --git a/api/dashboard/ig/dash_ig_view.py b/api/dashboard/ig/dash_ig_view.py index 908fc1b7..912d2637 100644 --- a/api/dashboard/ig/dash_ig_view.py +++ b/api/dashboard/ig/dash_ig_view.py @@ -8,6 +8,7 @@ from utils.types import RoleType, WebHookActions, WebHookCategory from utils.utils import CommonUtils, DiscordWebhooks from .dash_ig_serializer import ( + InterestGroupDetailSerializer, InterestGroupSerializer, InterestGroupCreateUpdateSerializer, ) @@ -58,7 +59,7 @@ def get(self, request): def post(self, request): user_id = JWTUtils.fetch_user_id(request) - request_data = request.data + request_data = request.data.copy() request_data["created_by"] = request_data["updated_by"] = user_id @@ -254,7 +255,7 @@ def get(self, request, pk): general_message="Interest Group Does Not Exist" ).get_failure_response() - serializer = InterestGroupSerializer(ig_data, many=False) + serializer = InterestGroupDetailSerializer(ig_data, many=False) return CustomResponse( response={"interestGroup": serializer.data} diff --git a/api/dashboard/learningcircle/learningcircle_views.py b/api/dashboard/learningcircle/learningcircle_views.py index dafe43b3..748d576d 100644 --- a/api/dashboard/learningcircle/learningcircle_views.py +++ b/api/dashboard/learningcircle/learningcircle_views.py @@ -2,7 +2,9 @@ import requests from rest_framework.views import APIView from db.learning_circle import LearningCircle, CircleMeetingLog, CircleMeetingAttendees -from db.user import UserInterests + +# from db.user import UserInterests +from db.user import UserDomains from utils.karma import add_karma from utils.permission import CustomizePermission, JWTUtils from utils.response import CustomResponse @@ -518,9 +520,10 @@ def get(self, request): ).get_failure_response() if user_id and not category and category != "all": user_id = JWTUtils.fetch_user_id(request) - interests = UserInterests.objects.filter(user_id=user_id).first() - if interests: - category = interests.choosen_interests + category = UserDomains.objects.filter(user_id=user_id).values_list( + "domain_name", flat=True + ) + if category != "all" and type(category) == str: category = [category] # if not no_location and not lat and not lon: diff --git a/api/dashboard/user/dash_user_serializer.py b/api/dashboard/user/dash_user_serializer.py index fe15326e..444c40b2 100644 --- a/api/dashboard/user/dash_user_serializer.py +++ b/api/dashboard/user/dash_user_serializer.py @@ -6,12 +6,13 @@ from db.organization import Department, Organization, UserOrganizationLink from db.task import UserIgLink -from db.user import Role, User, UserRoleLink +from db.user import Role, User, UserDomains, UserRoleLink from utils.permission import JWTUtils from utils.types import OrganizationType, RoleType from utils.utils import DateTimeUtils from db.user import DynamicRole, DynamicUser -from db.user import UserInterests + +# from db.user import UserInterests BE_DOMAIN_NAME = decouple_config("BE_DOMAIN_NAME") @@ -39,7 +40,8 @@ class UserSerializer(serializers.ModelSerializer): joined = serializers.CharField(source="created_at") roles = serializers.SerializerMethodField() dynamic_type = serializers.SerializerMethodField() - interest_selected = serializers.SerializerMethodField() + user_domains = serializers.SerializerMethodField() + user_endgoals = serializers.SerializerMethodField() class Meta: model = User @@ -55,13 +57,19 @@ class Meta: "roles", "profile_pic", "dynamic_type", - "interest_selected", + "user_domains", + "user_endgoals", ] - def get_interest_selected(self, obj): - if not UserInterests.objects.filter(user=obj).exists(): - return "Please select your interests" - return None + # def get_interest_selected(self, obj): + # if not UserInterests.objects.filter(user=obj).exists(): + # return "Please select your interests" + # return None + def get_user_domains(self, obj): + return obj.user_domains.values_list("domain_name", flat=True) + + def get_user_endgoals(self, obj): + return obj.user_endgoals.values_list("endgoal_name", flat=True) def get_roles(self, obj): return [ diff --git a/api/dashboard/user/dash_user_views.py b/api/dashboard/user/dash_user_views.py index 23a0e68d..fd773e59 100644 --- a/api/dashboard/user/dash_user_views.py +++ b/api/dashboard/user/dash_user_views.py @@ -26,7 +26,13 @@ def get(self, request): user_muid = JWTUtils.fetch_muid(request) # user = cache.get(f"db_user_{user_muid}") # if not user: - user = User.objects.filter(muid=user_muid).first() + user = ( + User.objects.prefetch_related( + "user_domains", "user_endgoals", "user_role_link_user" + ) + .filter(muid=user_muid) + .first() + ) cache.set(f"db_user_{user_muid}", user, timeout=60) if user is None: return CustomResponse( diff --git a/api/register/register_views.py b/api/register/register_views.py index d765cd26..f78cbbd3 100644 --- a/api/register/register_views.py +++ b/api/register/register_views.py @@ -4,7 +4,7 @@ from db.organization import Country, Department, District, Organization, State, Zone from django.utils.decorators import method_decorator from db.task import InterestGroup -from db.user import Role, User, UserInterests +from db.user import Role, User, UserDomains, UserEndgoals from utils.response import CustomResponse from utils.types import OrganizationType from . import serializers @@ -60,54 +60,109 @@ def get(self, request): ).get_success_response() -class UserInterestAPI(APIView): +class UserDomainSelectionAPI(APIView): permission_classes = [CustomizePermission] - def put(self, request): - if not JWTUtils.is_jwt_authenticated(request): - return CustomResponse( - general_message="Unauthorized access" - ).get_failure_response() + def post(self, request): user_id = JWTUtils.fetch_user_id(request) - if not (user := cache.get(f"db_user_{user_id}")): - user = User.objects.filter(id=user_id).first() - user_interest = UserInterests.objects.filter(user=user).first() - if not user_interest: + domains = request.data.get("domains") + if not domains or not isinstance(domains, list) or not len(domains) > 0: return CustomResponse( - general_message="User interests not found" - ).get_failure_response() - serializer = serializers.UserInterestSerializer( - instance=user_interest, data=request.data, context={"user": user} - ) - if serializer.is_valid(): - serializer.update(user_interest, serializer.validated_data) + general_message="Domains is required." + ).get_failure_response(status_code=400) + try: + UserDomains.objects.filter(user_id=user_id).delete() + UserDomains.objects.bulk_create( + [UserDomains(domain_name=domain, user_id=user_id) for domain in domains] + ) return CustomResponse( - general_message="Updated interests" + general_message="Domains selected" ).get_success_response() - return CustomResponse(general_message=serializer.errors).get_failure_response() + except Exception as e: + print("Exception during domain selection:", e) + return CustomResponse( + general_message="An unexpected error occured" + ).get_failure_response(500) + + +class UserEndgoalSelectionAPI(APIView): + permission_classes = [CustomizePermission] def post(self, request): - if not JWTUtils.is_jwt_authenticated(request): - return CustomResponse( - general_message="Unauthorized access" - ).get_failure_response() user_id = JWTUtils.fetch_user_id(request) - if not (user := cache.get(f"db_user_{user_id}")): - user = User.objects.filter(id=user_id).first() - user_interest = UserInterests.objects.filter(user=user).first() - if user_interest: + endgoals = request.data.get("endgoals") + if not endgoals or not isinstance(endgoals, list) or not len(endgoals) > 0: return CustomResponse( - general_message="User interests already exist" - ).get_failure_response() - serializer = serializers.UserInterestSerializer( - data=request.data, context={"user": user} - ) - if serializer.is_valid(): - serializer.save() + general_message="Endgoals is required." + ).get_failure_response(status_code=400) + try: + UserEndgoals.objects.filter(user_id=user_id).delete() + UserEndgoals.objects.bulk_create( + [ + UserEndgoals(endgoal_name=endgoal, user_id=user_id) + for endgoal in endgoals + ] + ) return CustomResponse( - general_message="Added interests" + general_message="Endgoals selected" ).get_success_response() - return CustomResponse(general_message=serializer.errors).get_failure_response() + except Exception as e: + print("Exception during endgoal selection:", e) + return CustomResponse( + general_message="An unexpected error occured" + ).get_failure_response(500) + + +# class UserInterestAPI(APIView): +# permission_classes = [CustomizePermission] + +# def put(self, request): +# if not JWTUtils.is_jwt_authenticated(request): +# return CustomResponse( +# general_message="Unauthorized access" +# ).get_failure_response() +# user_id = JWTUtils.fetch_user_id(request) +# if not (user := cache.get(f"db_user_{user_id}")): +# user = User.objects.filter(id=user_id).first() +# user_interest = UserInterests.objects.filter(user=user).first() +# if not user_interest: +# return CustomResponse( +# general_message="User interests not found" +# ).get_failure_response() +# serializer = serializers.UserInterestSerializer( +# instance=user_interest, data=request.data, context={"user": user} +# ) +# if serializer.is_valid(): +# serializer.update(user_interest, serializer.validated_data) +# return CustomResponse( +# general_message="Updated interests" +# ).get_success_response() +# return CustomResponse(general_message=serializer.errors).get_failure_response() + +# def post(self, request): +# if not JWTUtils.is_jwt_authenticated(request): +# return CustomResponse( +# general_message="Unauthorized access" +# ).get_failure_response() + +# user_id = JWTUtils.fetch_user_id(request) +# if not (user := cache.get(f"db_user_{user_id}")): +# user = User.objects.filter(id=user_id).first() + +# user_interest = UserInterests.objects.filter(user=user).first() +# if user_interest: +# return CustomResponse( +# general_message="User interests already exist" +# ).get_failure_response() +# serializer = serializers.UserInterestSerializer( +# data=request.data, context={"user": user} +# ) +# if serializer.is_valid(): +# serializer.save() +# return CustomResponse( +# general_message="Added interests" +# ).get_success_response() +# return CustomResponse(general_message=serializer.errors).get_failure_response() class UnverifiedOrganizationCreateView(APIView): diff --git a/api/register/serializers.py b/api/register/serializers.py index bd990dda..88ff32ac 100644 --- a/api/register/serializers.py +++ b/api/register/serializers.py @@ -31,7 +31,6 @@ UserReferralLink, UserRoleLink, UserSettings, - UserInterests, ) from utils.exception import CustomException from utils.types import OrganizationType, RoleType @@ -363,88 +362,87 @@ class Meta: ] -class UserInterestSerializer(serializers.ModelSerializer): - id = serializers.CharField(read_only=True) - user = serializers.CharField(read_only=True) - choosen_interests = serializers.JSONField() - other_interests = serializers.JSONField(required=False) - choosen_endgoals = serializers.JSONField() - other_endgoals = serializers.JSONField(required=False) - created_at = serializers.DateTimeField(read_only=True) - updated_at = serializers.DateTimeField(read_only=True) - - def create(self, validated_data): - validated_data["created_at"] = validated_data["updated_at"] = ( - DateTimeUtils.get_current_utc_time() - ) - if user := self.context.get("user"): - validated_data["user"] = user - else: - return serializers.ValidationError("User not found") - return super().create(validated_data) - - def update(self, instance, validated_data): - if validated_data.get("choosen_interests", None): - instance.choosen_interests = validated_data.get("choosen_interests", []) - if validated_data.get("other_interests", None): - instance.other_interests = validated_data.get("other_interests", []) - if validated_data.get("choosen_endgoals", None): - instance.choosen_endgoals = validated_data.get("choosen_endgoals", []) - if validated_data.get("other_endgoals", None): - instance.other_endgoals = validated_data.get("other_endgoals", []) - instance.updated_at = DateTimeUtils.get_current_utc_time() - return instance.save() - - def validate_choosen_interests(self, interests): - if not all( - interest in ("hardware", "coder", "creative", "manager", "others") - for interest in interests - ): - raise serializers.ValidationError("Invalid interests selected.") - return list(set(interests)) - - def validate_choosen_endgoals(self, end_goals): - if not all( - goal - in ( - "job", - "higher_education", - "gig_work", - "entrepreneurship", - "r&d", - "others", - ) - for goal in end_goals - ): - raise serializers.ValidationError("Invalid end goals selected.") - return list(set(end_goals)) - - class Meta: - model = UserInterests - fields = [ - "id", - "user", - "choosen_interests", - "other_interests", - "choosen_endgoals", - "other_endgoals", - "created_at", - "updated_at", - ] +# class UserInterestSerializer(serializers.ModelSerializer): +# id = serializers.CharField(read_only=True) +# user = serializers.CharField(read_only=True) +# choosen_interests = serializers.JSONField() +# other_interests = serializers.JSONField(required=False) +# choosen_endgoals = serializers.JSONField() +# other_endgoals = serializers.JSONField(required=False) +# created_at = serializers.DateTimeField(read_only=True) +# updated_at = serializers.DateTimeField(read_only=True) + +# def create(self, validated_data): +# validated_data["created_at"] = validated_data["updated_at"] = ( +# DateTimeUtils.get_current_utc_time() +# ) +# if user := self.context.get("user"): +# validated_data["user"] = user +# else: +# return serializers.ValidationError("User not found") +# return super().create(validated_data) + +# def update(self, instance, validated_data): +# if validated_data.get("choosen_interests", None): +# instance.choosen_interests = validated_data.get("choosen_interests", []) +# if validated_data.get("other_interests", None): +# instance.other_interests = validated_data.get("other_interests", []) +# if validated_data.get("choosen_endgoals", None): +# instance.choosen_endgoals = validated_data.get("choosen_endgoals", []) +# if validated_data.get("other_endgoals", None): +# instance.other_endgoals = validated_data.get("other_endgoals", []) +# instance.updated_at = DateTimeUtils.get_current_utc_time() +# return instance.save() + +# def validate_choosen_interests(self, interests): +# if not all( +# interest in ("hardware", "coder", "creative", "manager", "others") +# for interest in interests +# ): +# raise serializers.ValidationError("Invalid interests selected.") +# return list(set(interests)) + +# def validate_choosen_endgoals(self, end_goals): +# if not all( +# goal +# in ( +# "job", +# "higher_education", +# "gig_work", +# "entrepreneurship", +# "r&d", +# "others", +# ) +# for goal in end_goals +# ): +# raise serializers.ValidationError("Invalid end goals selected.") +# return list(set(end_goals)) + +# class Meta: +# model = UserInterests +# fields = [ +# "id", +# "user", +# "choosen_interests", +# "other_interests", +# "choosen_endgoals", +# "other_endgoals", +# "created_at", +# "updated_at", +# ] class RegisterSerializer(serializers.Serializer): user = UserSerializer() - interests = UserInterestSerializer(required=True) integration = IntegrationSerializer(required=False) referral = ReferralSerializer(required=False) def create(self, validated_data): with transaction.atomic(): user = UserSerializer().create(validated_data.pop("user")) - UserInterestSerializer(context={"user": user}).create( - validated_data.pop("interests") - ) + # UserInterestSerializer(context={"user": user}).create( + # validated_data.pop("interests") + # ) if integration := validated_data.pop("integration", None): integration.update({"user": user}) IntegrationSerializer().create(integration) diff --git a/api/register/urls.py b/api/register/urls.py index ef1b1c4f..c3d97246 100644 --- a/api/register/urls.py +++ b/api/register/urls.py @@ -22,7 +22,9 @@ path("user-country/", register_views.UserCountryAPI.as_view()), path("user-state/", register_views.UserStateAPI.as_view()), path("user-zone/", register_views.UserZoneAPI.as_view()), - path("interests/", register_views.UserInterestAPI.as_view()), + # path("interests/", register_views.UserInterestAPI.as_view()), + path("select-domains/", register_views.UserDomainSelectionAPI.as_view()), + path("select-endgoals/", register_views.UserEndgoalSelectionAPI.as_view()), path("connect-discord/", register_views.ConnectDiscordAPI.as_view()), path( "organization/create/", diff --git a/core/storage/__init__.py b/core/storage/__init__.py new file mode 100644 index 00000000..ad6ea82e --- /dev/null +++ b/core/storage/__init__.py @@ -0,0 +1,20 @@ +from django.conf import settings +from storages.backends.s3boto3 import S3Boto3Storage + + +class MediaStorage(S3Boto3Storage): + location = settings.MEDIAFILES_LOCATION + custom_domain = False + default_acl = "private" + + +class StaticStorage(S3Boto3Storage): + location = settings.STATICFILES_LOCATION + custom_domain = False + default_acl = "public-read" + + +class PublicStorage(S3Boto3Storage): + location = settings.PUBLIC_STORAGE_LOCATION + custom_domain = False + default_acl = "public-read" diff --git a/core/storage/fields.py b/core/storage/fields.py new file mode 100644 index 00000000..58e40ad3 --- /dev/null +++ b/core/storage/fields.py @@ -0,0 +1,21 @@ +from stdimage.models import StdImageField +from core.storage import PublicStorage, MediaStorage + + +class ResizedImageField(StdImageField): + def __init__(self, *args, **kwargs): + is_public = kwargs.get("is_public", False) + + if is_public: + kwargs.setdefault("storage", PublicStorage()) + else: + kwargs.setdefault("storage", MediaStorage()) + + kwargs.setdefault( + "variations", + { + "thumbnail": {"width": 100, "height": 100, "crop": False}, + "medium": {"width": 600, "height": 600, "crop": False}, + }, + ) + super().__init__(*args, **kwargs) diff --git a/db/task.py b/db/task.py index e88c4f03..cf0fd13d 100644 --- a/db/task.py +++ b/db/task.py @@ -1,7 +1,7 @@ import uuid from django.db import models - +from core.storage.fields import ResizedImageField from db.organization import Organization from django.conf import settings @@ -40,6 +40,10 @@ class InterestGroup(models.Model): name = models.CharField(max_length=75, unique=True) code = models.CharField(max_length=10, unique=True) icon = models.CharField(max_length=10) + logo = ResizedImageField(upload_to="interest_group/logos/", null=True, blank=False) + cover_image = ResizedImageField(upload_to="interest_group/cover_images/", null=True, blank=False) + short_description = models.CharField(max_length=200, null=True) + about = models.CharField(max_length=500, null=True) category =models.CharField(max_length=20,default="others",blank=False,null=False) updated_by = models.ForeignKey(User, on_delete=models.SET(settings.SYSTEM_ADMIN_ID), db_column="updated_by", related_name="interest_group_updated_by") diff --git a/db/user.py b/db/user.py index c3583ce2..cf135220 100644 --- a/db/user.py +++ b/db/user.py @@ -57,19 +57,42 @@ def save(self, *args, **kwargs): return super().save(*args, **kwargs) -class UserInterests(models.Model): - id = models.CharField(primary_key=True, max_length=36, default=uuid.uuid4) - user = models.ForeignKey(User, on_delete=models.CASCADE) - choosen_interests = models.JSONField(max_length=100) - other_interests = models.JSONField(max_length=100, blank=True, null=True) - choosen_endgoals = models.JSONField(max_length=100) - other_endgoals = models.JSONField(max_length=100, blank=True, null=True) +class UserDomains(models.Model): + id = models.CharField(primary_key=True, max_length=36, default=lambda: str(uuid.uuid4())) + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user_domains") + domain_name = models.CharField(max_length=50, null=False, blank=False) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + managed = False + db_table = 'user_domains' + +class UserEndgoals(models.Model): + id = models.CharField(primary_key=True, max_length=36, default=lambda: str(uuid.uuid4())) + user = models.ForeignKey(User, on_delete=models.CASCADE, null=False, blank=False, related_name="user_endgoals") + endgoal_name = models.CharField(max_length=50, null=False, blank=False) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: managed = False - db_table = 'user_interests' + db_table = 'user_endgoals' + +# class UserInterests(models.Model): +# id = models.CharField(primary_key=True, max_length=36, default=uuid.uuid4) +# user = models.ForeignKey(User, on_delete=models.CASCADE) +# choosen_interests = models.JSONField(max_length=100) +# other_interests = models.JSONField(max_length=100, blank=True, null=True) +# choosen_endgoals = models.JSONField(max_length=100) +# other_endgoals = models.JSONField(max_length=100, blank=True, null=True) +# created_at = models.DateTimeField(auto_now_add=True) +# updated_at = models.DateTimeField(auto_now=True) + +# class Meta: +# managed = False +# db_table = 'user_interests' + class UserMentor(models.Model): id = models.CharField(primary_key=True, max_length=36, default=uuid.uuid4) diff --git a/mulearnbackend/settings.py b/mulearnbackend/settings.py index 90fe6ff3..57fa4001 100644 --- a/mulearnbackend/settings.py +++ b/mulearnbackend/settings.py @@ -262,9 +262,29 @@ RAZORPAY_ID = decouple_config("RAZORPAY_ID") RAZORPAY_SECRET = decouple_config("RAZORPAY_SECRET") -DEFAULT_FILE_STORAGE = "django.core.files.storage.FileSystemStorage" +# DEFAULT_FILE_STORAGE = "django.core.files.storage.FileSystemStorage" import socket hostname, _, ips = socket.gethostbyname_ex(socket.gethostname()) INTERNAL_IPS = [f"{ip[:-1]}1" for ip in ips] + ["127.0.0.1", "10.0.2.2"] + +MEDIAFILES_LOCATION = decouple_config("MEDIAFILES_LOCATION") +STATICFILES_LOCATION = decouple_config("STATICFILES_LOCATION") +PUBLIC_STORAGE_LOCATION = decouple_config("PUBLIC_STORAGE_LOCATION") + +AWS_STORAGE_BUCKET_NAME = decouple_config("AWS_STORAGE_BUCKET_NAME") +AWS_S3_ACCESS_KEY_ID = decouple_config("AWS_S3_ACCESS_KEY_ID") +AWS_S3_SECRET_ACCESS_KEY = decouple_config("AWS_S3_SECRET_ACCESS_KEY") +# AWS_S3_REGION_NAME = decouple_config("AWS_S3_REGION_NAME") + +STORAGES = { + "default": { + "BACKEND": "core.storage.MediaStorage", + "OPTIONS": {}, + }, + "staticfiles": { + "BACKEND": "core.storage.StaticStorage", + "OPTIONS": {}, + }, +} diff --git a/requirements.txt b/requirements.txt index a154d616..88ef36db 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,4 +22,7 @@ pymysql==1.0.2 razorpay==1.4.2 reportlab==4.2.0 django_redis==5.4.0 -celery==5.4.0 \ No newline at end of file +celery==5.4.0 +boto3==1.36.24 +django-stdimage==6.0.2 +django-storages[s3]==1.14.5 \ No newline at end of file