Features: 1) Replace config.BASE_DOMAIN with settings.BASE_DOMAIN across the codebase; 2) Add support for dynamic STATIC_URL and MEDIA_URL based on initialization state; 3) Introduce INITIALIZED flag to determine application state;
Fixes: 1) Add missing import for `settings` in multiple modules; Extra: 1) Remove unused `SerializerMethodField` from serializers; 2) Update `RELEASE_DATE` to align with new version; 3) General cleanup and consistency adjustments.
This commit is contained in:
parent
01ba06d52c
commit
5f9f07d8f4
9 changed files with 31 additions and 40 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from constance import config
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ class AmoCRM:
|
||||||
payload = {
|
payload = {
|
||||||
"client_id": self.client_id,
|
"client_id": self.client_id,
|
||||||
"client_secret": self.client_secret,
|
"client_secret": self.client_secret,
|
||||||
"redirect_uri": f"https://api.{config.BASE_DOMAIN}/",
|
"redirect_uri": f"https://api.{settings.BASE_DOMAIN}/",
|
||||||
}
|
}
|
||||||
if self.refresh_token:
|
if self.refresh_token:
|
||||||
payload["grant_type"] = "refresh_token"
|
payload["grant_type"] = "refresh_token"
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ from contextlib import suppress
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from constance import config
|
from constance import config
|
||||||
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.db.models import Max, Min, QuerySet
|
from django.db.models import Max, Min, QuerySet
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
@ -136,7 +137,7 @@ class BrandType(DjangoObjectType): # type: ignore [misc]
|
||||||
|
|
||||||
def resolve_seo_meta(self: Brand, info) -> dict[str, str | list[Any] | dict[str, str] | None]:
|
def resolve_seo_meta(self: Brand, info) -> dict[str, str | list[Any] | dict[str, str] | None]:
|
||||||
lang = graphene_current_lang()
|
lang = graphene_current_lang()
|
||||||
base = f"https://{config.BASE_DOMAIN}"
|
base = f"https://{settings.BASE_DOMAIN}"
|
||||||
canonical = f"{base}/{lang}/brand/{self.slug}"
|
canonical = f"{base}/{lang}/brand/{self.slug}"
|
||||||
title = f"{self.name} | {config.PROJECT_NAME}"
|
title = f"{self.name} | {config.PROJECT_NAME}"
|
||||||
description = (self.description or "")[:180]
|
description = (self.description or "")[:180]
|
||||||
|
|
@ -262,7 +263,7 @@ class CategoryType(DjangoObjectType): # type: ignore [misc]
|
||||||
|
|
||||||
def resolve_seo_meta(self: Category, info):
|
def resolve_seo_meta(self: Category, info):
|
||||||
lang = graphene_current_lang()
|
lang = graphene_current_lang()
|
||||||
base = f"https://{config.BASE_DOMAIN}"
|
base = f"https://{settings.BASE_DOMAIN}"
|
||||||
canonical = f"{base}/{lang}/catalog/{self.slug}"
|
canonical = f"{base}/{lang}/catalog/{self.slug}"
|
||||||
title = f"{self.name} | {config.PROJECT_NAME}"
|
title = f"{self.name} | {config.PROJECT_NAME}"
|
||||||
description = (self.description or "")[:180]
|
description = (self.description or "")[:180]
|
||||||
|
|
@ -534,7 +535,7 @@ class ProductType(DjangoObjectType): # type: ignore [misc]
|
||||||
|
|
||||||
def resolve_seo_meta(self: Product, info):
|
def resolve_seo_meta(self: Product, info):
|
||||||
lang = graphene_current_lang()
|
lang = graphene_current_lang()
|
||||||
base = f"https://{config.BASE_DOMAIN}"
|
base = f"https://{settings.BASE_DOMAIN}"
|
||||||
canonical = f"{base}/{lang}/product/{self.slug}"
|
canonical = f"{base}/{lang}/product/{self.slug}"
|
||||||
title = f"{self.name} | {config.PROJECT_NAME}"
|
title = f"{self.name} | {config.PROJECT_NAME}"
|
||||||
description = (self.description or "")[:180]
|
description = (self.description or "")[:180]
|
||||||
|
|
|
||||||
|
|
@ -424,7 +424,7 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): #
|
||||||
def image_url(self) -> str:
|
def image_url(self) -> str:
|
||||||
with suppress(ValueError):
|
with suppress(ValueError):
|
||||||
url = str(self.image.url)
|
url = str(self.image.url)
|
||||||
url = url if "http" in url else f"https://api.{config.BASE_DOMAIN}{url}"
|
url = url if "http" in url else f"https://api.{settings.BASE_DOMAIN}{url}"
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -854,7 +854,7 @@ class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): # t
|
||||||
def image_url(self) -> str:
|
def image_url(self) -> str:
|
||||||
with suppress(ValueError):
|
with suppress(ValueError):
|
||||||
url = str(self.image.url)
|
url = str(self.image.url)
|
||||||
url = url if "http" in url else f"https://api.{config.BASE_DOMAIN}{url}"
|
url = url if "http" in url else f"https://api.{settings.BASE_DOMAIN}{url}"
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -1967,5 +1967,5 @@ class DigitalAssetDownload(ExportModelOperationsMixin("attribute_group"), NiceMo
|
||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
return (
|
return (
|
||||||
f"https://api.{config.BASE_DOMAIN}/download/{urlsafe_base64_encode(force_bytes(self.order_product.uuid))}"
|
f"https://api.{settings.BASE_DOMAIN}/download/{urlsafe_base64_encode(force_bytes(self.order_product.uuid))}"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ class CategoryDetailListSerializer(ListSerializer):
|
||||||
|
|
||||||
class CategoryDetailSerializer(ModelSerializer):
|
class CategoryDetailSerializer(ModelSerializer):
|
||||||
children = SerializerMethodField()
|
children = SerializerMethodField()
|
||||||
image = SerializerMethodField()
|
|
||||||
filterable_attributes = SerializerMethodField()
|
filterable_attributes = SerializerMethodField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -75,9 +74,6 @@ class CategoryDetailSerializer(ModelSerializer):
|
||||||
"modified",
|
"modified",
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_image(self, obj: Category) -> str:
|
|
||||||
return obj.image_url
|
|
||||||
|
|
||||||
def get_filterable_attributes(self, obj: Category) -> list[FilterableAttribute]:
|
def get_filterable_attributes(self, obj: Category) -> list[FilterableAttribute]:
|
||||||
return obj.filterable_attributes
|
return obj.filterable_attributes
|
||||||
|
|
||||||
|
|
@ -159,8 +155,6 @@ class ProductTagDetailSerializer(ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ProductImageDetailSerializer(ModelSerializer):
|
class ProductImageDetailSerializer(ModelSerializer):
|
||||||
image = SerializerMethodField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ProductImage
|
model = ProductImage
|
||||||
fields = [
|
fields = [
|
||||||
|
|
@ -172,9 +166,6 @@ class ProductImageDetailSerializer(ModelSerializer):
|
||||||
"modified",
|
"modified",
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_image(self, obj: ProductImage) -> str:
|
|
||||||
return obj.image_url
|
|
||||||
|
|
||||||
|
|
||||||
class AttributeDetailSerializer(ModelSerializer):
|
class AttributeDetailSerializer(ModelSerializer):
|
||||||
categories = CategoryDetailSerializer(many=True)
|
categories = CategoryDetailSerializer(many=True)
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@ class AttributeGroupSimpleSerializer(ModelSerializer): # type: ignore [type-arg
|
||||||
|
|
||||||
class CategorySimpleSerializer(ModelSerializer): # type: ignore [type-arg]
|
class CategorySimpleSerializer(ModelSerializer): # type: ignore [type-arg]
|
||||||
children = SerializerMethodField()
|
children = SerializerMethodField()
|
||||||
image = SerializerMethodField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Category
|
model = Category
|
||||||
|
|
@ -54,9 +53,6 @@ class CategorySimpleSerializer(ModelSerializer): # type: ignore [type-arg]
|
||||||
"children",
|
"children",
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_image(self, obj: Category) -> str:
|
|
||||||
return obj.image_url
|
|
||||||
|
|
||||||
def get_children(self, obj: Category) -> dict[str, Any]:
|
def get_children(self, obj: Category) -> dict[str, Any]:
|
||||||
request = self.context.get("request")
|
request = self.context.get("request")
|
||||||
if request is not None and request.user.has_perm("view_category"):
|
if request is not None and request.user.has_perm("view_category"):
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
from constance import config
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
def get_flag_by_language(language: str) -> str:
|
def get_flag_by_language(language: str) -> str:
|
||||||
return f"https://api.{config.BASE_DOMAIN}/static/flags/{language}.png"
|
return f"https://api.{settings.BASE_DOMAIN}/static/flags/{language}.png"
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ def org_schema():
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "Organization",
|
"@type": "Organization",
|
||||||
"name": config.COMPANY_NAME,
|
"name": config.COMPANY_NAME,
|
||||||
"url": f"https://{config.BASE_DOMAIN}/",
|
"url": f"https://{settings.BASE_DOMAIN}/",
|
||||||
"logo": f"https://{config.BASE_DOMAIN}/static/logo.png",
|
"logo": f"https://{settings.BASE_DOMAIN}/static/logo.png",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -19,10 +19,10 @@ def website_schema():
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "WebSite",
|
"@type": "WebSite",
|
||||||
"name": config.PROJECT_NAME,
|
"name": config.PROJECT_NAME,
|
||||||
"url": f"https://{config.BASE_DOMAIN}/",
|
"url": f"https://{settings.BASE_DOMAIN}/",
|
||||||
"potentialAction": {
|
"potentialAction": {
|
||||||
"@type": "SearchAction",
|
"@type": "SearchAction",
|
||||||
"target": f"https://{config.BASE_DOMAIN}/search?q={{query}}",
|
"target": f"https://{settings.BASE_DOMAIN}/search?q={{query}}",
|
||||||
"query-input": "required name=query",
|
"query-input": "required name=query",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +56,7 @@ def product_schema(product, images, rating=None):
|
||||||
"priceCurrency": settings.CURRENCY_CODE,
|
"priceCurrency": settings.CURRENCY_CODE,
|
||||||
"availability": "https://schema.org/InStock" if stock.quantity > 0 else "https://schema.org/OutOfStock",
|
"availability": "https://schema.org/InStock" if stock.quantity > 0 else "https://schema.org/OutOfStock",
|
||||||
"sku": stock.sku,
|
"sku": stock.sku,
|
||||||
"url": f"https://{config.BASE_DOMAIN}/product/{product.slug}",
|
"url": f"https://{settings.BASE_DOMAIN}/product/{product.slug}",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
data = {
|
data = {
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,7 @@ class CategoryViewSet(EvibesViewSet):
|
||||||
|
|
||||||
title = f"{category.name} | {config.PROJECT_NAME}"
|
title = f"{category.name} | {config.PROJECT_NAME}"
|
||||||
description = (category.description or "")[:180]
|
description = (category.description or "")[:180]
|
||||||
canonical = f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/catalog/{category.slug}"
|
canonical = f"https://{settings.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/catalog/{category.slug}"
|
||||||
og_image = request.build_absolute_uri(category.image.url) if getattr(category, "image", None) else ""
|
og_image = request.build_absolute_uri(category.image.url) if getattr(category, "image", None) else ""
|
||||||
|
|
||||||
og = {
|
og = {
|
||||||
|
|
@ -283,10 +283,10 @@ class CategoryViewSet(EvibesViewSet):
|
||||||
}
|
}
|
||||||
tw = {"card": "summary_large_image", "title": title, "description": description}
|
tw = {"card": "summary_large_image", "title": title, "description": description}
|
||||||
|
|
||||||
crumbs = [("Home", f"https://{config.BASE_DOMAIN}/")]
|
crumbs = [("Home", f"https://{settings.BASE_DOMAIN}/")]
|
||||||
if category.get_ancestors().exists():
|
if category.get_ancestors().exists():
|
||||||
for c in category.get_ancestors():
|
for c in category.get_ancestors():
|
||||||
crumbs.append((c.name, f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/catalog/{c.slug}"))
|
crumbs.append((c.name, f"https://{settings.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/catalog/{c.slug}"))
|
||||||
crumbs.append((category.name, canonical))
|
crumbs.append((category.name, canonical))
|
||||||
|
|
||||||
json_ld = [org_schema(), website_schema(), breadcrumb_schema(crumbs), category_schema(category, canonical)]
|
json_ld = [org_schema(), website_schema(), breadcrumb_schema(crumbs), category_schema(category, canonical)]
|
||||||
|
|
@ -303,7 +303,7 @@ class CategoryViewSet(EvibesViewSet):
|
||||||
.distinct()[:24]
|
.distinct()[:24]
|
||||||
)
|
)
|
||||||
for p in qs:
|
for p in qs:
|
||||||
product_urls.append(f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/product/{p.slug}")
|
product_urls.append(f"https://{settings.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/product/{p.slug}")
|
||||||
if product_urls:
|
if product_urls:
|
||||||
json_ld.append(item_list_schema(product_urls))
|
json_ld.append(item_list_schema(product_urls))
|
||||||
|
|
||||||
|
|
@ -388,7 +388,7 @@ class BrandViewSet(EvibesViewSet):
|
||||||
|
|
||||||
title = f"{brand.name} | {config.PROJECT_NAME}"
|
title = f"{brand.name} | {config.PROJECT_NAME}"
|
||||||
description = (brand.description or "")[:180]
|
description = (brand.description or "")[:180]
|
||||||
canonical = f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/brand/{brand.slug}"
|
canonical = f"https://{settings.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/brand/{brand.slug}"
|
||||||
|
|
||||||
logo_url = (
|
logo_url = (
|
||||||
request.build_absolute_uri(brand.big_logo.url)
|
request.build_absolute_uri(brand.big_logo.url)
|
||||||
|
|
@ -408,7 +408,7 @@ class BrandViewSet(EvibesViewSet):
|
||||||
tw = {"card": "summary_large_image", "title": title, "description": description}
|
tw = {"card": "summary_large_image", "title": title, "description": description}
|
||||||
|
|
||||||
crumbs = [
|
crumbs = [
|
||||||
("Home", f"https://{config.BASE_DOMAIN}/"),
|
("Home", f"https://{settings.BASE_DOMAIN}/"),
|
||||||
(brand.name, canonical),
|
(brand.name, canonical),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -528,7 +528,7 @@ class ProductViewSet(EvibesViewSet):
|
||||||
rating = {"value": p.rating, "count": p.feedbacks_count}
|
rating = {"value": p.rating, "count": p.feedbacks_count}
|
||||||
title = f"{p.name} | {config.PROJECT_NAME}"
|
title = f"{p.name} | {config.PROJECT_NAME}"
|
||||||
description = (p.description or "")[:180]
|
description = (p.description or "")[:180]
|
||||||
canonical = f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/product/{p.slug}"
|
canonical = f"https://{settings.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/product/{p.slug}"
|
||||||
og = {
|
og = {
|
||||||
"title": title,
|
"title": title,
|
||||||
"description": description,
|
"description": description,
|
||||||
|
|
@ -538,10 +538,10 @@ class ProductViewSet(EvibesViewSet):
|
||||||
}
|
}
|
||||||
tw = {"card": "summary_large_image", "title": title, "description": description}
|
tw = {"card": "summary_large_image", "title": title, "description": description}
|
||||||
|
|
||||||
crumbs = [("Home", f"https://{config.BASE_DOMAIN}/")]
|
crumbs = [("Home", f"https://{settings.BASE_DOMAIN}/")]
|
||||||
if p.category:
|
if p.category:
|
||||||
for c in p.category.get_ancestors(include_self=True):
|
for c in p.category.get_ancestors(include_self=True):
|
||||||
crumbs.append((c.name, f"https://{config.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/catalog/{c.slug}"))
|
crumbs.append((c.name, f"https://{settings.BASE_DOMAIN}/{settings.LANGUAGE_CODE}/catalog/{c.slug}"))
|
||||||
crumbs.append((p.name, canonical))
|
crumbs.append((p.name, canonical))
|
||||||
|
|
||||||
json_ld = [org_schema(), website_schema()]
|
json_ld = [org_schema(), website_schema()]
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,16 @@ from typing import Any
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
EVIBES_VERSION = "2025.4"
|
EVIBES_VERSION = "2025.4"
|
||||||
RELEASE_DATE = datetime(2025, 9, 13)
|
RELEASE_DATE = datetime(2025, 11, 9)
|
||||||
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
||||||
|
INITIALIZED = (BASE_DIR / ".initialized").exists()
|
||||||
|
|
||||||
SECRET_KEY = getenv("SECRET_KEY", "SUPER_SECRET_KEY")
|
SECRET_KEY = getenv("SECRET_KEY", "SUPER_SECRET_KEY")
|
||||||
DEBUG = bool(int(getenv("DEBUG", "1")))
|
DEBUG = bool(int(getenv("DEBUG", "1")))
|
||||||
|
|
||||||
|
BASE_DOMAIN: str = getenv("EVIBES_BASE_DOMAIN", "localhost")
|
||||||
|
|
||||||
ALLOWED_HOSTS: set[str] = {
|
ALLOWED_HOSTS: set[str] = {
|
||||||
"app",
|
"app",
|
||||||
"worker",
|
"worker",
|
||||||
|
|
@ -294,10 +297,10 @@ TIME_ZONE: str = getenv("TIME_ZONE", "Europe/London")
|
||||||
|
|
||||||
WHITENOISE_MANIFEST_STRICT: bool = False
|
WHITENOISE_MANIFEST_STRICT: bool = False
|
||||||
|
|
||||||
STATIC_URL: str = "/static/"
|
STATIC_URL: str = f"https://api.{BASE_DOMAIN}/static/" if INITIALIZED else "static/"
|
||||||
STATIC_ROOT: Path = BASE_DIR / "static"
|
STATIC_ROOT: Path = BASE_DIR / "static"
|
||||||
|
|
||||||
MEDIA_URL: str = "/media/"
|
MEDIA_URL: str = f"https://api.{BASE_DOMAIN}/media/" if INITIALIZED else "media/"
|
||||||
MEDIA_ROOT: Path = BASE_DIR / "media"
|
MEDIA_ROOT: Path = BASE_DIR / "media"
|
||||||
|
|
||||||
AUTH_USER_MODEL: str = "vibes_auth.User"
|
AUTH_USER_MODEL: str = "vibes_auth.User"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue