#!/usr/bin/env python # -*- coding: utf-8 -*- ''' Django views. ''' from django.shortcuts import render, redirect, get_object_or_404 from django.urls import reverse_lazy from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.views.generic.detail import SingleObjectMixin from django.views.generic import ListView from django.views import View from django.http import Http404 from django.contrib import messages from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin from django.contrib.messages.views import SuccessMessageMixin from .forms import ( ExplorerCreationForm, PlaceForm, PlaceImageCreateForm ) from .models import Place, PlaceImage, Voucher, PhotoAlbum # Create your views here. # BaseView that checks if user is logged in. class IsAuthenticated(LoginRequiredMixin, View): redirect_field_name = 'redirect_to' permission_denied_message = 'Please login to proceed' def handle_no_permission(self): messages.error(self.request, self.permission_denied_message) return super().handle_no_permission() # BaseView that checks if logged in user is submitter of place. class IsPlaceSubmitter(UserPassesTestMixin, View): place_submitter_error_message = None def get_place(self): pass def test_func(self): """ Check if user is eligible to modify place. """ if not hasattr(self.request, 'user'): return False if self.request.user.is_superuser: return True # Check if currently logged in user was the submitter place_obj = self.get_place() if place_obj and hasattr(place_obj, 'submitted_by') and self.request.user == place_obj.submitted_by: return True if self.place_submitter_error_message: messages.error(self.request, self.place_submitter_error_message) return False class SignUpView(SuccessMessageMixin, CreateView): form_class = ExplorerCreationForm success_url = reverse_lazy('login') template_name = 'signup.html' success_message = 'User created.' class PlaceListView(IsAuthenticated, ListView): paginate_by = 5 model = Place template_name = 'place/place_list.html' ordering = ['name'] def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['place_map_center'] = Place.average_latlon(context['place_list']) return context class PlaceDetailView(IsAuthenticated, View): def get(self, request, pk): place = Place.objects.get(pk=pk) context = { 'place': place, 'place_list': [ place ], 'place_map_center': [ place.latitude, place.longitude ] } return render(request, 'place/place_detail.html', context) class HomeView(View): def get(self, request, *args, **kwargs): place_list = Place.objects.all().order_by('-submitted_when')[:10] place_map_center = Place.average_latlon(place_list) context = { 'place_list': place_list, 'place_map_center': place_map_center } return render(request, 'home.html', context) class PlaceUpdateView(IsAuthenticated, IsPlaceSubmitter, SuccessMessageMixin, UpdateView): template_name = 'place/place_update.html' model = Place form_class = PlaceForm success_message = 'Successfully updated place.' place_submitter_error_message = 'You do no have permissions to alter 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(IsAuthenticated, View): def get(self, request, *args, **kwargs): place_image_form = PlaceImageCreateForm() 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 place = place_form.save(commit=False) # Save logged in user as "submitted_by" place.submitted_by = submitter place.save() if request.FILES: self._apply_multipart_image_upload( files=request.FILES.getlist('filename'), place=place, submitter=submitter ) kwargs_to_pass = { 'pk': place.pk } messages.success( self.request, 'Successfully created place.') return redirect(reverse_lazy('place_detail', kwargs=kwargs_to_pass)) else: context = { 'form': form_place } # Usually the browser should have checked the form before sending. messages.error( self.request, 'Please fill in all required fields.') return render(request, 'place/place_create.html', context) def _apply_multipart_image_upload(self, files, place, submitter): for image in files: place_image = PlaceImage.objects.create( filename=image, place=place, submitted_by=submitter ) place_image.save() class PlaceDeleteView(IsAuthenticated, IsPlaceSubmitter, DeleteView): template_name = 'place/place_delete.html' model = Place success_message = 'Successfully deleted place.' success_url = reverse_lazy('place_list') success_message = 'Place deleted' place_submitter_error_message = 'You do no have permission 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 PhotoAlbumCreateView(IsAuthenticated, SuccessMessageMixin, CreateView): model = PhotoAlbum fields = ['url', 'label'] template_name = 'photo_album/photo_album_create.html' success_message = 'Photo Album submitted' def get(self, request, place_id, *args, **kwargs): self.place = Place.objects.get(pk=place_id) return super().get(request, *args, **kwargs) def post(self, request, place_id, *args, **kwargs): self.place = Place.objects.get(pk=place_id) response = super().post(request, *args, **kwargs) self.object.place = self.place self.object.submitted_by = request.user self.object.save() return response def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['place'] = self.place return context def get_success_url(self): return reverse_lazy('place_detail', kwargs={'pk': self.place.id}) class PhotoAlbumDeleteView(IsAuthenticated, IsPlaceSubmitter, SingleObjectMixin, View): model = PhotoAlbum pk_url_kwarg = 'pk' success_message = 'Photo Album deleted' def get_place(self): place_id = self.get_object().place.id return Place.objects.get(pk=place_id) def test_func(self): can_edit_place = super().test_func() if can_edit_place: return True if self.get_object().submitted_by == self.request.user: return True messages.error(self.request, 'You do not have permissions to alter this photo album') return False def get(self, request, *args, **kwargs): place_id = self.get_object().place.id self.get_object().delete() messages.success(self.request, self.success_message) return redirect(reverse_lazy('place_detail', kwargs={'pk': place_id}))