227 lines
8.1 KiB
Python
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 |