schon/engine/core/utils/seo_builders.py

104 lines
3 KiB
Python

from constance import config
from django.conf import settings
from engine.core.models import Product
def org_schema():
return {
"@context": "https://schema.org",
"@type": "Organization",
"name": config.COMPANY_NAME,
"url": f"https://{config.BASE_DOMAIN}/",
"logo": f"https://{config.BASE_DOMAIN}/static/logo.png",
}
def website_schema():
return {
"@context": "https://schema.org",
"@type": "WebSite",
"name": config.PROJECT_NAME,
"url": f"https://{config.BASE_DOMAIN}/",
"potentialAction": {
"@type": "SearchAction",
"target": f"https://{config.BASE_DOMAIN}/search?q={{query}}",
"query-input": "required name=query",
},
}
def breadcrumb_schema(items):
return {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{"@type": "ListItem", "position": i + 1, "name": name, "item": url} for i, (name, url) in enumerate(items)
],
}
def item_list_schema(urls):
return {
"@context": "https://schema.org",
"@type": "ItemList",
"itemListElement": [{"@type": "ListItem", "position": i + 1, "url": u} for i, u in enumerate(urls)],
}
def product_schema(product, images, rating=None):
offers = []
for stock in product.stocks.all():
offers.append(
{
"@type": "Offer",
"price": round(stock.price, 2),
"priceCurrency": settings.CURRENCY_CODE,
"availability": "https://schema.org/InStock" if stock.quantity > 0 else "https://schema.org/OutOfStock",
"sku": stock.sku,
"url": f"https://{config.BASE_DOMAIN}/product/{product.slug}",
}
)
data = {
"@context": "https://schema.org",
"@type": "Product",
"name": product.name,
"description": product.description or "",
"sku": product.partnumber or "",
"brand": {"@type": "Brand", "name": product.brand.name} if product.brand else None,
"image": [img.image.url for img in images] or [],
"offers": offers[:1] if offers else None,
}
if rating and rating["count"] > 0:
data["aggregateRating"] = {
"@type": "AggregateRating",
"ratingValue": rating["value"],
"reviewCount": rating["count"],
}
return {k: v for k, v in data.items() if v not in (None, [], {})}
def category_schema(category, url):
return {
"@context": "https://schema.org",
"@type": "CollectionPage",
"name": category.name,
"description": category.description or "",
"url": url,
}
def brand_schema(brand, url, logo_url=None):
data = {
"@context": "https://schema.org",
"@type": "Brand",
"name": brand.name,
"url": url,
}
if logo_url:
data["logo"] = logo_url
return data
def any_non_digital() -> bool:
return Product.objects.filter(is_digital=False).exists()