#!/usr/bin/env python # -*- coding: utf-8 -*- from datetime import timedelta from django.db.models.functions import Lower from django.views import View from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.views.generic.detail import SingleObjectMixin from django.contrib import messages from django.contrib.messages.views import SuccessMessageMixin from django.utils.translation import gettext as _ from django.utils import timezone from django.shortcuts import render, redirect, get_object_or_404 from django.urls import reverse_lazy, reverse from lostplaces.models import ( Place, PlaceImage, PlaceVoting, PLACE_LEVELS ) from lostplaces.views.base_views import ( IsAuthenticatedMixin, IsPlaceSubmitterMixin, LevelCapPlaceListView, IsEligibleToSeePlaceMixin ) from lostplaces.views.place_image_views import MultiplePlaceImageUploadMixin from lostplaces.forms import PlaceForm, PlaceImageForm, TagSubmitForm from lostplaces.common import redirect_referer_or from taggit.models import Tag class PlaceListView(IsAuthenticatedMixin, LevelCapPlaceListView): paginate_by = 18 template_name = 'place/place_list.html' ordering = [Lower('name')] def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['mapping_config'] = { 'all_points': context['place_list'], 'map_center': Place.average_latlon(context['place_list']) } return context class PlaceDetailView(IsAuthenticatedMixin, IsEligibleToSeePlaceMixin, View): not_eligible_to_see_message = _('You\'r not allowed to see this place') def get_place(self): return get_object_or_404(Place, pk=self.kwargs['pk']) def get(self, request, pk): place = self.get_place() place.calculate_place_level() explorer = request.user.explorer if place.mode == 'draft': messages.info( self.request, _('This place is still in draft mode and only visible to the submitter and superusers') ) elif place.mode == 'imported': messages.info( self.request, _('This place was imported and not reviewed & correted yet. This place is visbible for superusers only and does not appear in the list views.') ) context = { 'place': place, 'mapping_config': { 'all_points': [ place ], 'map_center': {'latitude': place.latitude, 'longitude': place.longitude}, }, 'tagging_config': { 'all_tags': Tag.objects.all(), 'submit_form': TagSubmitForm(), 'tagged_item': place, 'submit_url': reverse('place_tag_submit', kwargs={'tagged_id': place.id}), 'delete_url_name': 'place_tag_delete' }, 'placevoting': { 'users_vote': PlaceVoting.objects.filter(place=place, submitted_by=explorer).first(), 'all_choices': reversed(PLACE_LEVELS), 'accuracy': place.calculate_voting_accuracy() } } return render(request, 'place/place_detail.html', context) class PlaceUpdateView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, SuccessMessageMixin, UpdateView): template_name = 'place/place_update.html' model = Place form_class = PlaceForm success_message = _('Successfully updated place') place_submitter_error_message = _('You are not allowed to edit this place') def get_success_url(self): return reverse_lazy('place_detail', kwargs={'pk':self.get_object().pk}) def get_place(self): return self.get_object() class PlaceCreateView(MultiplePlaceImageUploadMixin, IsAuthenticatedMixin, View): def get(self, request, *args, **kwargs): place_image_form = PlaceImageForm() place_form = PlaceForm() context = { 'place_form': place_form, 'place_image_form': place_image_form } return render(request, 'place/place_create.html', context) def post(self, request, *args, **kwargs): place_form = PlaceForm(request.POST) if place_form.is_valid(): submitter = request.user.explorer place = place_form.save(commit=False) # Save logged in user as "submitted_by" place.submitted_by = submitter if place_form.cleaned_data['draft']: place.mode = 'draft'; place.save() self.handle_place_images(request, place) messages.success( self.request, _('Successfully created place') ) return redirect(reverse_lazy('place_detail', kwargs={'pk': place.pk})) else: # Usually the browser should have checked the form before sending. messages.error( self.request, _('Please fill in all required fields.') ) return render( request=request, template_name='place/place_create.html', context={ 'place_form': place_form, 'place_image_form': PlaceImageForm() }, status=400 ) class PlaceDeleteView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, DeleteView): template_name = 'place/place_delete.html' model = Place success_message = _('Successfully deleted place') success_url = reverse_lazy('place_list') place_submitter_error_message = _('You are not allowed to delete this place') def delete(self, request, *args, **kwargs): messages.success(self.request, self.success_message) return super().delete(request, *args, **kwargs) def get_place(self): return self.get_object() class PlaceFavoriteView(IsAuthenticatedMixin, IsEligibleToSeePlaceMixin, View): not_eligible_to_see_message = _('You\'r not allowed to favorite this place') def get_place(self): return get_object_or_404(Place, pk=self.kwargs['place_id']) def get(self, request, place_id): place = self.get_place() if request.user is not None: request.user.explorer.favorite_places.add(place) request.user.explorer.save() return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk})) class PlaceUnfavoriteView(IsAuthenticatedMixin, View): def get(self, request, place_id): place = get_object_or_404(Place, id=place_id) if request.user is not None: request.user.explorer.favorite_places.remove(place) request.user.explorer.save() return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk})) class PlaceVisitCreateView(IsAuthenticatedMixin, IsEligibleToSeePlaceMixin, View): not_eligible_to_see_message = _('You\'r not allowed to visit this place :P (Now please stop trying out URL\'s)') def get_place(self): return get_object_or_404(Place, pk=self.kwargs['place_id']) def get(self, request, place_id): place = self.get_place() if request.user is not None: request.user.explorer.visited_places.add(place) request.user.explorer.save() return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk})) class PlaceVisitDeleteView(IsAuthenticatedMixin, View): def get(self, request, place_id): place = get_object_or_404(Place, id=place_id) if request.user is not None: request.user.explorer.visited_places.remove(place) request.user.explorer.save() return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk})) class PlaceVoteView(IsEligibleToSeePlaceMixin, View): delta = timedelta(weeks=24) def get_place(self): return get_object_or_404(Place, pk=self.kwargs['place_id']) def get(self, request, place_id, vote): place = self.get_place() explorer = request.user.explorer voting = PlaceVoting.objects.filter( submitted_by=explorer, place=place ).first() if voting is None: voting = PlaceVoting.objects.create( submitted_by=explorer, place=place, vote=vote ) messages.success(self.request, _('Vote submitted')) else: voting.submitted_when = timezone.now() voting.vote = vote messages.success(self.request, _('Your vote has been update')) voting.save() return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))