224 lines
7.8 KiB
Python
224 lines
7.8 KiB
Python
import mimetypes
|
|
|
|
from django.http import FileResponse, Http404
|
|
from django.shortcuts import get_object_or_404
|
|
from django.urls import reverse
|
|
from django.views import View
|
|
from django.views.generic import DetailView, ListView, TemplateView
|
|
|
|
from .models import Article, ArticleCitation, ArticleSection, MainProduct, ProductVideo, SubProduct, SubProductVersion
|
|
from .release_assets import FILE_FIELD_BY_ASSET_KEY, RELEASE_ASSET_KEYS, URL_FIELD_BY_ASSET_KEY
|
|
from .release_context import build_archive_context, build_release_context
|
|
|
|
VIDEO_PREVIEW_LIMIT = 3
|
|
VIDEO_ARCHIVE_PAGE_SIZE = 6
|
|
|
|
|
|
def _product_video_preview(queryset, archive_url):
|
|
total = queryset.count()
|
|
return {
|
|
"product_videos": queryset[:VIDEO_PREVIEW_LIMIT],
|
|
"videos_total_count": total,
|
|
"videos_archive_url": archive_url if total > VIDEO_PREVIEW_LIMIT else "",
|
|
}
|
|
|
|
|
|
class ReleaseAssetDownloadView(View):
|
|
def get(self, request, version_id, asset):
|
|
if asset not in RELEASE_ASSET_KEYS:
|
|
raise Http404
|
|
version = get_object_or_404(SubProductVersion, pk=version_id, is_active=True)
|
|
parent = version.sub_product or version.main_product
|
|
if parent is None or not parent.is_active:
|
|
raise Http404
|
|
url_field = URL_FIELD_BY_ASSET_KEY[asset]
|
|
if (getattr(version, url_field) or "").strip():
|
|
raise Http404
|
|
file_field = FILE_FIELD_BY_ASSET_KEY[asset]
|
|
release_file = getattr(version, file_field)
|
|
if not release_file:
|
|
raise Http404
|
|
filename = version.release_download_filename(asset)
|
|
content_type, _ = mimetypes.guess_type(filename)
|
|
return FileResponse(
|
|
release_file.open("rb"),
|
|
as_attachment=True,
|
|
filename=filename,
|
|
content_type=content_type or "application/octet-stream",
|
|
)
|
|
|
|
|
|
class ProductOverviewView(ListView):
|
|
model = MainProduct
|
|
template_name = "products/overview.html"
|
|
context_object_name = "main_products"
|
|
queryset = MainProduct.objects.filter(is_active=True).prefetch_related(
|
|
"sub_products"
|
|
)
|
|
|
|
|
|
class MainProductDetailView(DetailView):
|
|
model = MainProduct
|
|
template_name = "products/main_detail.html"
|
|
context_object_name = "main_product"
|
|
slug_url_kwarg = "main_slug"
|
|
queryset = MainProduct.objects.filter(is_active=True).prefetch_related(
|
|
"sub_products"
|
|
)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context["articles"] = self.object.articles.prefetch_related(
|
|
"sections", "citations"
|
|
).all()
|
|
videos = self.object.videos.filter(is_active=True).order_by("order", "pk")
|
|
context.update(
|
|
_product_video_preview(
|
|
videos,
|
|
reverse("products:main_product_videos", kwargs={"main_slug": self.object.slug}),
|
|
)
|
|
)
|
|
release_context = build_release_context(
|
|
self.object.distribution,
|
|
self.object.versions.filter(is_active=True),
|
|
self.object,
|
|
)
|
|
release_context["versions_archive_url"] = self.object.get_versions_archive_url()
|
|
context.update(release_context)
|
|
return context
|
|
|
|
|
|
class MainProductOlderVersionsView(TemplateView):
|
|
template_name = "products/versions_archive.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
main_product = get_object_or_404(
|
|
MainProduct,
|
|
slug=self.kwargs["main_slug"],
|
|
is_active=True,
|
|
)
|
|
active_versions = main_product.versions.filter(is_active=True)
|
|
context["main_product"] = main_product
|
|
context["sub_product"] = None
|
|
context["product_detail_url"] = main_product.get_absolute_url()
|
|
context.update(
|
|
build_archive_context(
|
|
main_product.distribution, active_versions, main_product
|
|
)
|
|
)
|
|
return context
|
|
|
|
|
|
class SubProductDetailView(TemplateView):
|
|
template_name = "products/sub_detail.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
main_product = get_object_or_404(
|
|
MainProduct,
|
|
slug=self.kwargs["main_slug"],
|
|
is_active=True,
|
|
)
|
|
sub_product = get_object_or_404(
|
|
SubProduct,
|
|
slug=self.kwargs["sub_slug"],
|
|
main_product=main_product,
|
|
is_active=True,
|
|
)
|
|
context["main_product"] = main_product
|
|
context["sub_product"] = sub_product
|
|
context["articles"] = sub_product.articles.prefetch_related(
|
|
"sections", "citations"
|
|
).all()
|
|
videos = sub_product.videos.filter(is_active=True).order_by("order", "pk")
|
|
context.update(
|
|
_product_video_preview(
|
|
videos,
|
|
reverse(
|
|
"products:sub_product_videos",
|
|
kwargs={"main_slug": main_product.slug, "sub_slug": sub_product.slug},
|
|
),
|
|
)
|
|
)
|
|
context["siblings"] = (
|
|
SubProduct.objects.filter(main_product=main_product, is_active=True)
|
|
.exclude(pk=sub_product.pk)
|
|
.order_by("order", "name")
|
|
)
|
|
active_versions = sub_product.versions.filter(is_active=True)
|
|
release_context = build_release_context(
|
|
sub_product.distribution, active_versions, sub_product
|
|
)
|
|
release_context["versions_archive_url"] = sub_product.get_versions_archive_url()
|
|
context.update(release_context)
|
|
return context
|
|
|
|
|
|
class ProductVideoArchiveView(ListView):
|
|
model = ProductVideo
|
|
template_name = "videos/archive.html"
|
|
context_object_name = "videos"
|
|
paginate_by = VIDEO_ARCHIVE_PAGE_SIZE
|
|
|
|
def get_parent(self):
|
|
main_product = get_object_or_404(
|
|
MainProduct,
|
|
slug=self.kwargs["main_slug"],
|
|
is_active=True,
|
|
)
|
|
sub_slug = self.kwargs.get("sub_slug")
|
|
if sub_slug:
|
|
return get_object_or_404(
|
|
SubProduct,
|
|
slug=sub_slug,
|
|
main_product=main_product,
|
|
is_active=True,
|
|
)
|
|
return main_product
|
|
|
|
def get_queryset(self):
|
|
self.parent_object = self.get_parent()
|
|
return self.parent_object.videos.filter(is_active=True).order_by("order", "pk")
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context.update(
|
|
{
|
|
"library_title": f"{self.parent_object.name} videos",
|
|
"library_description": "Tutorials, demonstrations, and technical guides.",
|
|
"library_back_url": self.parent_object.get_absolute_url(),
|
|
"library_back_label": f"Back to {self.parent_object.name}",
|
|
"pagination_range": context["paginator"].get_elided_page_range(context["page_obj"].number),
|
|
}
|
|
)
|
|
return context
|
|
|
|
|
|
class SubProductOlderVersionsView(TemplateView):
|
|
template_name = "products/versions_archive.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
main_product = get_object_or_404(
|
|
MainProduct,
|
|
slug=self.kwargs["main_slug"],
|
|
is_active=True,
|
|
)
|
|
sub_product = get_object_or_404(
|
|
SubProduct,
|
|
slug=self.kwargs["sub_slug"],
|
|
main_product=main_product,
|
|
is_active=True,
|
|
)
|
|
active_versions = sub_product.versions.filter(is_active=True)
|
|
context["main_product"] = main_product
|
|
context["sub_product"] = sub_product
|
|
context["product_detail_url"] = sub_product.get_absolute_url()
|
|
context.update(
|
|
build_archive_context(
|
|
sub_product.distribution, active_versions, sub_product
|
|
)
|
|
)
|
|
return context
|