348 lines
12 KiB
Python
348 lines
12 KiB
Python
import io
|
|
from functools import reduce
|
|
from operator import or_
|
|
|
|
from cms.utils import get_page_url_without_locale, most_strict_site_match
|
|
from django import forms
|
|
from django.conf import settings
|
|
from django.contrib.admin.views.decorators import staff_member_required
|
|
from django.contrib.sites.models import Site
|
|
from django.db.models import Count, F, Q
|
|
from django.db.models.functions import Length
|
|
from django.http import FileResponse, JsonResponse
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
from django.utils.decorators import method_decorator
|
|
from django.views import View
|
|
from django.views.generic.edit import FormView
|
|
from rest_framework.exceptions import ValidationError
|
|
from rest_framework.views import APIView
|
|
from wagtail.core.models import Locale, Page
|
|
|
|
from catalog.labels import create_label_1, create_label_3, register_font
|
|
from catalog.models import Ad, Comment, Item, Tag, item_tags
|
|
|
|
from .serializers import CommentSerializer
|
|
|
|
|
|
def index(request):
|
|
try:
|
|
default = Site.objects.get(config__default=True)
|
|
except Site.DoesNotExist:
|
|
default = Site.objects.first()
|
|
|
|
return redirect(default.domain)
|
|
|
|
def catalog(request):
|
|
return render(request, "catalog/index.html")
|
|
|
|
|
|
class LabelForm(forms.Form):
|
|
# inventory_nr = forms.CharField()
|
|
title = forms.CharField()
|
|
date = forms.CharField()
|
|
participant = forms.CharField()
|
|
categories = forms.CharField()
|
|
description = forms.CharField(widget=forms.Textarea)
|
|
|
|
def create_label(self):
|
|
register_font()
|
|
buffer = io.BytesIO()
|
|
create_label_1(buffer, "",
|
|
self.cleaned_data['title'],
|
|
self.cleaned_data['date'],
|
|
self.cleaned_data['participant'],
|
|
self.cleaned_data['categories'],
|
|
self.cleaned_data['description'])
|
|
buffer.seek(0)
|
|
return buffer
|
|
|
|
|
|
class LabelView(FormView):
|
|
template_name = 'catalog/label.html'
|
|
form_class = LabelForm
|
|
success_url = '/labels/create/'
|
|
|
|
@method_decorator(staff_member_required)
|
|
def dispatch(self, *args, **kwargs):
|
|
return super().dispatch(*args, **kwargs)
|
|
|
|
def form_valid(self, form):
|
|
buffer = form.create_label()
|
|
return FileResponse(buffer, as_attachment=False, filename='label.pdf')
|
|
|
|
|
|
class ItemLabelView(View):
|
|
|
|
@method_decorator(staff_member_required)
|
|
def dispatch(self, *args, **kwargs):
|
|
return super().dispatch(*args, **kwargs)
|
|
|
|
def create_label(self, obj):
|
|
register_font()
|
|
buffer = io.BytesIO()
|
|
tags_str = item_tags(obj.tags.filter(is_active=True), hide_categories=['object_type', 'who'])
|
|
create_label_1(buffer, obj.inventory_number_eb, obj.title_short or "",
|
|
obj.date_short or "", obj.participant_short or "",
|
|
tags_str, obj.description_short or '')
|
|
buffer.seek(0)
|
|
return buffer
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
obj = get_object_or_404(Item, pk=kwargs.get('id'))
|
|
buffer = self.create_label(obj)
|
|
return FileResponse(buffer, as_attachment=False, filename='label.pdf')
|
|
|
|
|
|
class ItemBackLabelView(View):
|
|
|
|
@method_decorator(staff_member_required)
|
|
def dispatch(self, *args, **kwargs):
|
|
return super().dispatch(*args, **kwargs)
|
|
|
|
def create_label(self, obj):
|
|
register_font()
|
|
buffer = io.BytesIO()
|
|
tags_str = item_tags(obj.tags.filter(is_active=True), hide_categories=['object_type', 'who'])
|
|
create_label_3(buffer, obj.history_short or "", obj.participant_short or "")
|
|
buffer.seek(0)
|
|
return buffer
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
obj = get_object_or_404(Item, pk=kwargs.get('id'))
|
|
buffer = self.create_label(obj)
|
|
return FileResponse(buffer, as_attachment=False, filename='label.pdf')
|
|
|
|
|
|
def get_website_mode(request, default_mode, default_host='www.e-fundbuero.ch'):
|
|
"""Get the website mode: internal/external/minimal."""
|
|
models_dict = getattr(settings, 'WEBSITE_MODE', {})
|
|
host = request.META.get('HTTP_HOST', default_host)
|
|
try:
|
|
return models_dict.get(host, default_mode)
|
|
except KeyError:
|
|
return default_mode
|
|
|
|
|
|
class SearchJSONView(View):
|
|
def filter_by_tags(self, qs, tags, update_display_count=True):
|
|
"""
|
|
Filtering a QS with given tags.
|
|
|
|
We group tag per "category". And we filter with following rule:
|
|
tags within a group are using "OR"
|
|
different groups of tags are using "AND"
|
|
|
|
For example, "30er", "40er" and "foto" should be filtered like this:
|
|
objects with "30er" or "40" and and with "foto".
|
|
"""
|
|
|
|
# grouping tags
|
|
tags_list = Tag.objects.filter(slug__in=tags.split(","))
|
|
tags_with_categories = {}
|
|
for tag in tags_list:
|
|
if tag.category not in tags_with_categories.keys():
|
|
tags_with_categories[tag.category] = []
|
|
tags_with_categories[tag.category].append(tag)
|
|
|
|
# Filtering
|
|
for tags_l in tags_with_categories.values():
|
|
qs = qs.filter(reduce(or_, [ Q(tags=tag) for tag in tags_l]))
|
|
|
|
# updating tags count
|
|
if update_display_count:
|
|
tags_list.update(display_count=F("display_count") + 1)
|
|
|
|
return qs.distinct()
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
query = request.GET.get("query", None)
|
|
tags = request.GET.get("tags", None) # ?tags=slug1;slug2
|
|
site = request.GET.get("site", settings.SITE_ID)
|
|
results = []
|
|
qs = Item.objects.filter(is_active=True)
|
|
if tags is not None and len(tags) > 0:
|
|
qs = self.filter_by_tags(qs, tags)
|
|
|
|
elif query is not None and len(query) > 0:
|
|
query = query.strip()
|
|
if len(query) > 0:
|
|
filters = (
|
|
Q(title__icontains=query)
|
|
| Q(description_short__icontains=query)
|
|
| Q(history_short__icontains=query)
|
|
| Q(inventory_number__icontains=query)
|
|
| Q(inventory_number_eb__icontains=query)
|
|
| Q(participant_short__icontains=query)
|
|
| Q(date_short__icontains=query)
|
|
| Q(title_short__icontains=query)
|
|
)
|
|
if query.startswith("i-"):
|
|
filters |= Q(id=query[2:])
|
|
|
|
qs = qs.filter(filters)
|
|
|
|
qs = qs.filter(site=site)
|
|
qs = qs.annotate(
|
|
num_comments=Count("comments", filter=Q(comments__status=Comment.VALIDATED)),
|
|
image_length=Length('image')
|
|
)
|
|
qs = qs.prefetch_related('tags', 'group')
|
|
mode = get_website_mode(request, 'minimal')
|
|
if mode == 'external':
|
|
qs = qs.exclude(
|
|
Q(Q(image__isnull=True) | Q(image_length__exact=0))
|
|
& Q(youtube_url__isnull=True)
|
|
)
|
|
else:
|
|
qs = qs.exclude(Q(image__isnull=True) | Q(image_length__exact=0))
|
|
for obj in qs:
|
|
results.append(obj.export_as_json())
|
|
return JsonResponse({"catalog": results, "count": len(results)})
|
|
|
|
|
|
class TagsJSONView(View):
|
|
def get(self, request, *args, **kwargs):
|
|
site = request.GET.get("site", settings.SITE_ID)
|
|
data = {
|
|
category: list(
|
|
Item.objects.filter(Q(site=site, tags__category=category, tags__is_active=True))
|
|
.exclude(tags__name="")
|
|
.distinct()
|
|
.values(name=F("tags__name"), slug=F("tags__slug")).order_by("tags__name")
|
|
)
|
|
for category, _ in Tag.CATEGORIES
|
|
}
|
|
|
|
return JsonResponse(data)
|
|
|
|
|
|
class ModeJSONView(View):
|
|
def get(self, request, *args, **kwargs):
|
|
mode = get_website_mode(request, 'minimal')
|
|
return JsonResponse({'mode': mode})
|
|
|
|
|
|
class AdsJSONView(View):
|
|
def get(self, request, *args, **kwargs):
|
|
ads_list = []
|
|
ads = Ad.objects.filter(site=request.GET.get("site", settings.SITE_ID))
|
|
for ad in ads:
|
|
video_fr = ''
|
|
if ad.video_fr:
|
|
video_fr = ad.video_fr.url
|
|
video_it = ''
|
|
if ad.video_it:
|
|
video_it = ad.video_it.url
|
|
video_en = ''
|
|
if ad.video_en:
|
|
video_en = ad.video_en.url
|
|
ads_list.append(
|
|
{
|
|
"de": ad.video_de.url,
|
|
"de_title": ad.title_de,
|
|
"de_text": ad.text_de,
|
|
"fr": video_fr,
|
|
"fr_title": ad.title_fr,
|
|
"fr_text": ad.text_fr,
|
|
"en": video_en,
|
|
"en_title": ad.title_en,
|
|
"en_text": ad.text_en,
|
|
"it": video_it,
|
|
"it_title": ad.title_it,
|
|
"it_text": ad.text_it,
|
|
"prio": ad.prio,
|
|
"show_per_page": ad.show_per_page
|
|
}
|
|
)
|
|
return JsonResponse({"results": ads_list, "count": len(ads_list)})
|
|
|
|
|
|
class ItemJSONView(View):
|
|
def get(self, request, *args, **kwargs):
|
|
obj = get_object_or_404(Item, pk=kwargs["id"], is_active=True)
|
|
return JsonResponse(obj.export_as_json())
|
|
|
|
|
|
def get_pages(site, locale):
|
|
all_pages = Page.objects.all().filter(locale=locale).exclude(url_path="/")
|
|
pages_except_relative_root = filter(lambda p: get_page_url_without_locale(p) != site.domain, all_pages)
|
|
pages_for_this_site = [
|
|
p for p in pages_except_relative_root if most_strict_site_match(p) == site and p.live is True
|
|
]
|
|
return pages_for_this_site
|
|
|
|
class SitesJSONView(View):
|
|
def get(self, request, *args, **kwargs):
|
|
result = dict()
|
|
active_locale = Locale.get_active()
|
|
|
|
for site in Site.objects.all():
|
|
result[site.domain] = {
|
|
'id': site.id,
|
|
'name': site.name,
|
|
'urls': {
|
|
page.localized.title if not page.specific.menu_link_text else page.specific.menu_link_text: (page.get_url(), page.show_in_menus)
|
|
for page in get_pages(site, active_locale)
|
|
},
|
|
'color': site.config.color,
|
|
'scrolling_text': site.config.scrolling_text,
|
|
'default': site.config.default
|
|
}
|
|
return JsonResponse(result)
|
|
|
|
|
|
class ItemCommentsJSONView(View): # (LoginRequiredMixin, View)
|
|
"""
|
|
View to fetch / create comments related to an item. Need to be logged-in.
|
|
"""
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
"""Return thr"""
|
|
obj = get_object_or_404(Item, pk=kwargs["id"])
|
|
qs = Comment.objects.filter(item=obj, status=Comment.VALIDATED)
|
|
results = []
|
|
for comment in qs:
|
|
results.append(
|
|
{
|
|
"added_on": str(comment.added_on),
|
|
"author": comment.author,
|
|
"field_specific": comment.field_specific,
|
|
"status": comment.get_status_display(),
|
|
"comment": comment.comment,
|
|
}
|
|
)
|
|
return JsonResponse({"results": results, "count": len(results)})
|
|
|
|
|
|
class ParticipateJSONView(APIView):
|
|
authentication_classes = []
|
|
|
|
def get(self, request):
|
|
return JsonResponse({"msg": "this endpoint is only available through POST."})
|
|
|
|
def post(self, request):
|
|
try:
|
|
serializer = CommentSerializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
user_data = serializer.validated_data
|
|
|
|
comment = Comment.objects.create(
|
|
object_id=user_data.get("object_id", None),
|
|
object_type=user_data.get("object_type", None),
|
|
description=user_data["desc"],
|
|
attachment=user_data["file"],
|
|
first_name=user_data["first_name"],
|
|
last_name=user_data["last_name"],
|
|
birth_year=user_data.get("birth_year"),
|
|
address=user_data.get("address"),
|
|
post_code=user_data.get("post_code"),
|
|
city=user_data.get("city"),
|
|
phone=user_data.get("phone"),
|
|
email=user_data["mail"],
|
|
keep=user_data.get("keep", None),
|
|
site=Site.objects.get(id=settings.SITE_ID)
|
|
)
|
|
return JsonResponse({"status": "ok"})
|
|
except ValidationError as exc:
|
|
return JsonResponse(exc.detail)
|