furry/products/sitemap_views.py

227 lines
8.1 KiB
Python

"""
Sitemap und Robots.txt Views für SEO
"""
from django.http import HttpResponse
from django.template.loader import render_to_string
from django.views.decorators.cache import cache_page
from django.utils.decorators import method_decorator
from django.views import View
from django.contrib.sites.models import Site
from .models import Product, Category
from .seo import SEOManager
import xml.etree.ElementTree as ET
import json
@cache_page(60 * 60 * 24) # 24 Stunden Cache
def sitemap_xml(request):
"""XML Sitemap generieren"""
seo_manager = SEOManager(request)
sitemap_data = seo_manager.generate_sitemap_xml()
# XML generieren
root = ET.Element('urlset')
root.set('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9')
for url_data in sitemap_data['urlset']['url']:
url_elem = ET.SubElement(root, 'url')
loc = ET.SubElement(url_elem, 'loc')
loc.text = url_data['loc']
lastmod = ET.SubElement(url_elem, 'lastmod')
lastmod.text = url_data['lastmod']
changefreq = ET.SubElement(url_elem, 'changefreq')
changefreq.text = url_data['changefreq']
priority = ET.SubElement(url_elem, 'priority')
priority.text = url_data['priority']
# XML als String
xml_string = ET.tostring(root, encoding='unicode', method='xml')
response = HttpResponse(xml_string, content_type='application/xml')
response['Content-Type'] = 'application/xml; charset=utf-8'
return response
@cache_page(60 * 60 * 24) # 24 Stunden Cache
def robots_txt(request):
"""Robots.txt generieren"""
seo_manager = SEOManager(request)
robots_content = seo_manager.generate_robots_txt()
response = HttpResponse(robots_content, content_type='text/plain')
return response
class SitemapView(View):
"""Erweiterte Sitemap View mit Kategorisierung"""
@method_decorator(cache_page(60 * 60 * 24))
def get(self, request):
"""Sitemap mit Kategorisierung"""
site = Site.objects.get_current()
base_url = f"https://{site.domain}"
# Sitemap Index
if request.GET.get('type') == 'index':
return self.sitemap_index(request, base_url)
# Produkt-Sitemap
elif request.GET.get('type') == 'products':
return self.products_sitemap(request, base_url)
# Kategorie-Sitemap
elif request.GET.get('type') == 'categories':
return self.categories_sitemap(request, base_url)
# Standard-Sitemap
else:
return self.main_sitemap(request, base_url)
def sitemap_index(self, request, base_url):
"""Sitemap Index"""
root = ET.Element('sitemapindex')
root.set('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9')
sitemaps = [
{'loc': f"{base_url}/sitemap.xml", 'lastmod': '2024-01-15'},
{'loc': f"{base_url}/sitemap.xml?type=products", 'lastmod': '2024-01-15'},
{'loc': f"{base_url}/sitemap.xml?type=categories", 'lastmod': '2024-01-15'},
]
for sitemap in sitemaps:
sitemap_elem = ET.SubElement(root, 'sitemap')
loc = ET.SubElement(sitemap_elem, 'loc')
loc.text = sitemap['loc']
lastmod = ET.SubElement(sitemap_elem, 'lastmod')
lastmod.text = sitemap['lastmod']
xml_string = ET.tostring(root, encoding='unicode', method='xml')
response = HttpResponse(xml_string, content_type='application/xml')
return response
def products_sitemap(self, request, base_url):
"""Produkt-Sitemap"""
root = ET.Element('urlset')
root.set('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9')
products = Product.objects.filter(is_active=True).order_by('-updated_at')
for product in products:
url_elem = ET.SubElement(root, 'url')
loc = ET.SubElement(url_elem, 'loc')
loc.text = f"{base_url}{product.get_absolute_url()}"
lastmod = ET.SubElement(url_elem, 'lastmod')
lastmod.text = product.updated_at.strftime('%Y-%m-%d')
changefreq = ET.SubElement(url_elem, 'changefreq')
changefreq.text = 'weekly'
priority = ET.SubElement(url_elem, 'priority')
priority.text = '0.8'
xml_string = ET.tostring(root, encoding='unicode', method='xml')
response = HttpResponse(xml_string, content_type='application/xml')
return response
def categories_sitemap(self, request, base_url):
"""Kategorie-Sitemap"""
root = ET.Element('urlset')
root.set('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9')
categories = Category.objects.all()
for category in categories:
url_elem = ET.SubElement(root, 'url')
loc = ET.SubElement(url_elem, 'loc')
loc.text = f"{base_url}{category.get_absolute_url()}"
lastmod = ET.SubElement(url_elem, 'lastmod')
lastmod.text = '2024-01-15' # TODO: Kategorie updated_at hinzufügen
changefreq = ET.SubElement(url_elem, 'changefreq')
changefreq.text = 'weekly'
priority = ET.SubElement(url_elem, 'priority')
priority.text = '0.7'
xml_string = ET.tostring(root, encoding='unicode', method='xml')
response = HttpResponse(xml_string, content_type='application/xml')
return response
def main_sitemap(self, request, base_url):
"""Haupt-Sitemap mit statischen Seiten"""
root = ET.Element('urlset')
root.set('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9')
# Statische Seiten
static_pages = [
{'url': '/', 'priority': '1.0', 'changefreq': 'daily'},
{'url': '/products/', 'priority': '0.8', 'changefreq': 'weekly'},
{'url': '/gallery/', 'priority': '0.7', 'changefreq': 'weekly'},
{'url': '/contact/', 'priority': '0.5', 'changefreq': 'monthly'},
{'url': '/about/', 'priority': '0.5', 'changefreq': 'monthly'},
{'url': '/faq/', 'priority': '0.6', 'changefreq': 'monthly'},
{'url': '/custom-order/', 'priority': '0.7', 'changefreq': 'weekly'},
]
for page in static_pages:
url_elem = ET.SubElement(root, 'url')
loc = ET.SubElement(url_elem, 'loc')
loc.text = f"{base_url}{page['url']}"
lastmod = ET.SubElement(url_elem, 'lastmod')
lastmod.text = '2024-01-15'
changefreq = ET.SubElement(url_elem, 'changefreq')
changefreq.text = page['changefreq']
priority = ET.SubElement(url_elem, 'priority')
priority.text = page['priority']
xml_string = ET.tostring(root, encoding='unicode', method='xml')
response = HttpResponse(xml_string, content_type='application/xml')
return response
def manifest_json(request):
"""Web App Manifest für PWA"""
manifest = {
"name": "Kasico Fursuit Shop",
"short_name": "Kasico",
"description": "Premium Fursuit Shop - Handgefertigte Fursuits made in Germany",
"start_url": "/",
"display": "standalone",
"background_color": "#FF6B9D",
"theme_color": "#FF6B9D",
"orientation": "portrait-primary",
"icons": [
{
"src": "/static/images/kasicoLogo.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/static/images/kasicoLogo.png",
"sizes": "512x512",
"type": "image/png"
}
],
"categories": ["shopping", "fashion"],
"lang": "de",
"dir": "ltr"
}
response = HttpResponse(
json.dumps(manifest, indent=2),
content_type='application/json'
)
return response