From 4f7b84194b056b5d6d9acca4cceb2cabc04fd8a5 Mon Sep 17 00:00:00 2001 From: luxagraf Date: Sat, 29 Dec 2018 08:37:39 -0600 Subject: cleaned up JS and made modal handler. --- apps/notes/views.py | 154 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 111 insertions(+), 43 deletions(-) (limited to 'apps/notes/views.py') diff --git a/apps/notes/views.py b/apps/notes/views.py index 5d55720..6751340 100644 --- a/apps/notes/views.py +++ b/apps/notes/views.py @@ -1,6 +1,11 @@ from django.views.generic import CreateView, ListView, UpdateView, DeleteView from django.views.generic.detail import DetailView -from django.views.generic.base import View, RedirectView +from django.views.generic.edit import FormView, ModelFormMixin +from django.http import JsonResponse +from django.core import serializers +from django.forms import modelformset_factory +from django.db.models import Count +from django.views.generic.base import RedirectView from django.utils.decorators import method_decorator from django.contrib.auth.decorators import login_required from django.shortcuts import get_object_or_404, render, redirect @@ -14,10 +19,25 @@ from rest_framework import permissions from .serializers import NoteSerializer, NotebookSerializer, NoteTagSerializer from .models import Note, Notebook, LuxTag from .forms import NoteForm, NotebookForm +from utils.views import AjaxableResponseMixin + +################## +# Base Views +################## + + +@method_decorator(login_required, name='dispatch') +class BaseListView(ListView): + pass + + +@method_decorator(login_required, name='dispatch') +class BaseDetailView(DetailView): + pass @method_decorator(login_required, name='dispatch') -class LoggedInViewWithUser(View): +class LoggedInViewWithUser(FormView): def get_form_kwargs(self, **kwargs): kwargs = super().get_form_kwargs(**kwargs) @@ -25,12 +45,23 @@ class LoggedInViewWithUser(View): return kwargs -class NoteListView(LoggedInViewWithUser, ListView): +################## +# Note Views +################## + + +class NoteListView(BaseListView): model = Note def get_queryset(self): if not self.request.user.is_anonymous: - return Note.objects.filter(owner=self.request.user) + return Note.objects.prefetch_related('tags').filter(owner=self.request.user).select_related('notebook') + + def get_context_data(self, **kwargs): + context = super(NoteListView, self).get_context_data(**kwargs) + context['notebook_list'] = Notebook.objects.filter(owner=self.request.user).exclude(name="Trash").annotate(note_count=Count('note')) + context['tag_list'] = LuxTag.objects.filter(note__owner=self.request.user).annotate(note_count=Count('note')) + return context def get_template_names(self): # print("IP Address for debug-toolbar: " + self.request.META['REMOTE_ADDR']) @@ -40,36 +71,10 @@ class NoteListView(LoggedInViewWithUser, ListView): return ['sell.html'] -class NoteTagView(LoggedInViewWithUser, ListView): - model = Note - template_name = 'notes/notes_list.html' - - def get_queryset(self): - ''' - This can generate a crazy amount of joins if there's a lot of tags - have to keep an eye on it. Would be better to do: - from django.db.models import Q - from functools import reduce - from operator import and_, or_ - #query = reduce(and_, (Q(tags__slug=t) for t in self.tag_list)) - # Note.objects.filter(query, owner=self.request.user) - But that doesn't work for some reason. - ''' - if not self.request.user.is_anonymous: - self.tag_list = [x.strip() for x in self.kwargs['slug'].split("+")] - qs = Note.objects.filter(owner=self.request.user) - for tag in self.tag_list: - qs = qs.filter(tags__slug=tag) - return qs - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context['notes_list'] = Note.objects.filter(owner=self.request.user) - context['tags'] = self.tag_list - return context - - -class NoteDetailView(UpdateView, LoggedInViewWithUser): +class NoteDetailView(LoggedInViewWithUser, AjaxableResponseMixin, UpdateView): + ''' + POST only works as AJAX + ''' model = Note form_class = NoteForm template_name = 'notes/notes_detail.html' @@ -80,11 +85,20 @@ class NoteDetailView(UpdateView, LoggedInViewWithUser): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['notes_list'] = Note.objects.filter(owner=self.request.user) + context['notebook_form'] = NotebookForm return context + def form_valid(self, form): + self.object = form.save() + tags = serializers.serialize("json", self.object.tags.all()) + data = { + 'tags': tags, + 'notebook': {'name': self.object.notebook.name, 'color': self.object.notebook.color_rgb} + } + return JsonResponse(data, safe=True) + -class NoteCreateView(CreateView, LoggedInViewWithUser): +class NoteCreateView(LoggedInViewWithUser, CreateView): model = Note form_class = NoteForm template_name = 'notes/notes_create.html' @@ -99,27 +113,76 @@ class NoteCreateView(CreateView, LoggedInViewWithUser): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['notes_list'] = Note.objects.filter(owner=self.request.user).select_related() + context['notebook_form'] = NotebookForm + # context['notes_list'] = Note.objects.filter(owner=self.request.user).select_related() + return context + + +class NoteTagView(BaseListView): + model = Note + template_name = 'notes/notes_list.html' + + def get_queryset(self): + ''' + This can generate a crazy amount of joins if there's a lot of tags + have to keep an eye on it. Would be better to do: + from django.db.models import Q + from functools import reduce + from operator import and_, or_ + #query = reduce(and_, (Q(tags__slug=t) for t in self.tag_list)) + # Note.objects.filter(query, owner=self.request.user) + But that doesn't work for some reason. + ''' + if not self.request.user.is_anonymous: + try: + tags = self.kwargs['slug'].split("+") + except ValueError: + tags = self.kwargs['slug'] + self.tag_list = [x.strip() for x in tags] + qs = Note.objects.prefetch_related('tags').filter(owner=self.request.user).select_related('notebook') + for tag in self.tag_list: + qs = qs.filter(tags__slug=tag) + return qs + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + #context['notes_list'] = Note.objects.filter(owner=self.request.user) + context['tags'] = LuxTag.objects.filter(slug__in=self.tag_list) return context -class NotebookListView(CreateView, LoggedInViewWithUser): +################## +# Notebook Views +################## + + +class NotebookListView(LoggedInViewWithUser, CreateView): model = Notebook form_class = NotebookForm - template_name = 'notes/notebook_create.html' + template_name = 'notes/notebook_list.html' def get_queryset(self): if not self.request.user.is_anonymous: return Notebook.objects.filter(owner=self.request.user) + def form_valid(self, form): + form.instance.owner = self.request.user + self.object = form.save() + return super(NotebookListView, self).form_valid(form) + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['notebook_list'] = Notebook.objects.filter(owner=self.request.user) - context['notes_list'] = Note.objects.filter(owner=self.request.user).select_related() + NotebookFormSet = modelformset_factory(Notebook, form=NotebookForm, extra=0) + context['notebook_form_list'] = NotebookFormSet(queryset=Notebook.objects.filter(owner=self.request.user).exclude(name="Trash").select_related().annotate(note_count=Count('note'))) + #context['notebook_list'] = Notebook.objects.filter(owner=self.request.user).exclude(name="Trash").select_related().annotate(note_count=Count('note')) + #context['notes_list'] = Note.objects.filter(owner=self.request.user).select_related() return context + def get_success_url(self): + return reverse_lazy('notebooks:detail', kwargs={'slug': self.object.slug}) + -class NotebookDetailView(DetailView, LoggedInViewWithUser): +class NotebookDetailView(BaseDetailView): model = Notebook def get_object(self): @@ -129,11 +192,16 @@ class NotebookDetailView(DetailView, LoggedInViewWithUser): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['notes_list'] = Note.objects.filter(owner=self.request.user).select_related() + #context['notes_list'] = Note.objects.filter(owner=self.request.user).select_related() context['form'] = self.form return context +################## +# API Views +################## + + class IsOwnerOrDeny(permissions.BasePermission): """ Custom permission to only allow owners to post to their endpoint -- cgit v1.2.3-70-g09d2