From 3f150dcfade9443b3435309cb928f330966eb749 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 26 Apr 2012 22:19:02 -0500 Subject: Migrate news views to class-based generic views Signed-off-by: Dan McGee --- news/views.py | 124 +++++++++++++++++++++++++++------------------------------- 1 file changed, 57 insertions(+), 67 deletions(-) (limited to 'news/views.py') diff --git a/news/views.py b/news/views.py index 7ac009ba..268f0523 100644 --- a/news/views.py +++ b/news/views.py @@ -1,38 +1,15 @@ +import markdown + from django import forms -from django.contrib.auth.decorators import permission_required from django.http import HttpResponse from django.shortcuts import get_object_or_404, redirect from django.template.defaultfilters import slugify -from django.views.decorators.cache import never_cache -from django.views.generic import list_detail, create_update -from django.views.generic.simple import direct_to_template - -import markdown +from django.views.decorators.http import require_POST +from django.views.generic import (DetailView, ListView, + CreateView, UpdateView, DeleteView) from .models import News -def view_redirect(request, object_id): - newsitem = get_object_or_404(News, pk=object_id) - return redirect(newsitem, permanent=True) - -def view(request, slug=None): - return list_detail.object_detail(request, News.objects.all(), - slug=slug, - template_name="news/view.html", - template_object_name='news') - -#TODO: May as well use a date-based list here sometime -def news_list(request): - return list_detail.object_list(request, - News.objects.all().select_related('author').defer('content'), - paginate_by=50, - template_name="news/list.html", - template_object_name="news") - -class NewsForm(forms.ModelForm): - class Meta: - model = News - exclude = ('id', 'slug', 'author', 'postdate') def find_unique_slug(newsitem): '''Attempt to find a unique slug for this news item.''' @@ -46,46 +23,59 @@ def find_unique_slug(newsitem): return suffixed -@permission_required('news.add_news') -@never_cache -def add(request): - if request.POST: - form = NewsForm(request.POST) - if form.is_valid(): - newsitem = form.save(commit=False) - newsitem.author = request.user - newsitem.slug = find_unique_slug(newsitem) - newsitem.save() - return redirect(newsitem) - else: - form = NewsForm() - return direct_to_template(request, 'news/add.html', { 'form': form }) - -@permission_required('news.delete_news') -@never_cache -def delete(request, slug): - return create_update.delete_object(request, - News, - slug=slug, - post_delete_redirect='/news/', - template_name='news/delete.html', - template_object_name='news') - -@permission_required('news.change_news') -@never_cache -def edit(request, slug): - return create_update.update_object(request, - slug=slug, - form_class=NewsForm, - template_name="news/add.html") - -@permission_required('news.change_news') -@never_cache + +class NewsForm(forms.ModelForm): + class Meta: + model = News + exclude = ('id', 'slug', 'author', 'postdate') + + +class NewsDetailView(DetailView): + model = News + template_name = "news/view.html" + + +class NewsListView(ListView): + queryset = News.objects.all().select_related('author').defer('content') + template_name = "news/list.html" + paginate_by = 50 + + +class NewsCreateView(CreateView): + model = News + form_class = NewsForm + template_name = "news/add.html" + + def form_valid(self, form): + # special logic, we auto-fill the author and slug fields + newsitem = form.save(commit=False) + newsitem.author = self.request.user + newsitem.slug = find_unique_slug(newsitem) + newsitem.save() + return super(NewsCreateView, self).form_valid(form) + + +class NewsEditView(UpdateView): + model = News + form_class = NewsForm + template_name = "news/add.html" + + +class NewsDeleteView(DeleteView): + model = News + template_name = "news/delete.html" + success_url = "/news/" + + +def view_redirect(request, object_id): + newsitem = get_object_or_404(News, pk=object_id) + return redirect(newsitem, permanent=True) + + +@require_POST def preview(request): - markup = '' - if request.POST: - data = request.POST.get('data', '') - markup = markdown.markdown(data) + data = request.POST.get('data', '') + markup = markdown.markdown(data) return HttpResponse(markup) # vim: set ts=4 sw=4 et: -- cgit v1.2.3-2-g168b From badc535aeb1d310a9b8aa59aade07045e6eae653 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 18 Apr 2012 15:05:43 -0500 Subject: Ensure order_by default value is cleared when using distinct() Otherwise the queryset returns nonsensical results. I find the design of this less than obvious but so be it; we can ensure the results work regardless of a default ordering on the model. Signed-off-by: Dan McGee --- news/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'news/views.py') diff --git a/news/views.py b/news/views.py index 268f0523..03f3b0ac 100644 --- a/news/views.py +++ b/news/views.py @@ -13,7 +13,8 @@ from .models import News def find_unique_slug(newsitem): '''Attempt to find a unique slug for this news item.''' - existing = list(News.objects.values_list('slug', flat=True).distinct()) + existing = list(News.objects.values_list( + 'slug', flat=True).order_by().distinct()) suffixed = slug = slugify(newsitem.title) suffix = 0 -- cgit v1.2.3-2-g168b From 0b97d52351fc2bdcae16f1a1e7c56afd4ed476ad Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 26 Oct 2012 16:49:58 -0500 Subject: Enable safe mode for markdown parsing Although we don't allow unauthenticated users to post content, we should still cover our bases here and ensure people can't inject stuff into the production website via an inadvertent XSS. Signed-off-by: Dan McGee --- news/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'news/views.py') diff --git a/news/views.py b/news/views.py index 03f3b0ac..c0230f1e 100644 --- a/news/views.py +++ b/news/views.py @@ -76,7 +76,7 @@ def view_redirect(request, object_id): @require_POST def preview(request): data = request.POST.get('data', '') - markup = markdown.markdown(data) + markup = markdown.markdown(data, safe_mode=True) return HttpResponse(markup) # vim: set ts=4 sw=4 et: -- cgit v1.2.3-2-g168b From 62bb3db8ada68a22c7a58f32b2e6bed63f19e53c Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 26 Oct 2012 17:36:12 -0500 Subject: Remove usages of 'django.contrib.markup' Switch to the news model being able to spit out the HTML version of the content, and don't use the markup contrib module. This is deprecated as of Django 1.5 so we can move off it now to save trouble down the road when it is fully removed. Signed-off-by: Dan McGee --- news/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'news/views.py') diff --git a/news/views.py b/news/views.py index c0230f1e..74bec058 100644 --- a/news/views.py +++ b/news/views.py @@ -76,7 +76,7 @@ def view_redirect(request, object_id): @require_POST def preview(request): data = request.POST.get('data', '') - markup = markdown.markdown(data, safe_mode=True) + markup = markdown.markdown(data, safe_mode=True, enable_attributes=False) return HttpResponse(markup) # vim: set ts=4 sw=4 et: -- cgit v1.2.3-2-g168b From ce5b0b2c5c10a3c840fd8aaa696ec2b8f403dc5b Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 31 Oct 2012 00:21:45 -0500 Subject: Disable markdown safe mode Unless we want older news items to look like [HTML_REMOVED]this[HTML_REMOVED] all over the place. I'm tempted to mark old items as non-safe but enforce safe mode for all new news postings. Signed-off-by: Dan McGee --- news/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'news/views.py') diff --git a/news/views.py b/news/views.py index 74bec058..52182800 100644 --- a/news/views.py +++ b/news/views.py @@ -76,7 +76,7 @@ def view_redirect(request, object_id): @require_POST def preview(request): data = request.POST.get('data', '') - markup = markdown.markdown(data, safe_mode=True, enable_attributes=False) + markup = markdown.markdown(data, safe_mode=False, enable_attributes=False) return HttpResponse(markup) # vim: set ts=4 sw=4 et: -- cgit v1.2.3-2-g168b From d616a40cf57d417775d7277a6d03f51c2967e8d9 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sun, 11 Nov 2012 15:47:44 -0600 Subject: Exclude news.safe_mode on news edit screen Signed-off-by: Dan McGee --- news/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'news/views.py') diff --git a/news/views.py b/news/views.py index 52182800..efd93fdb 100644 --- a/news/views.py +++ b/news/views.py @@ -28,7 +28,7 @@ def find_unique_slug(newsitem): class NewsForm(forms.ModelForm): class Meta: model = News - exclude = ('id', 'slug', 'author', 'postdate') + exclude = ('id', 'slug', 'author', 'postdate', 'safe_mode') class NewsDetailView(DetailView): -- cgit v1.2.3-2-g168b From fc7eb4aebf63525155bcadd366a87eed8f161568 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Wed, 28 Nov 2012 09:28:28 -0600 Subject: Add safe_mode filter to news admin; preview uses safe mode Signed-off-by: Dan McGee --- news/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'news/views.py') diff --git a/news/views.py b/news/views.py index efd93fdb..0e22ac34 100644 --- a/news/views.py +++ b/news/views.py @@ -76,7 +76,7 @@ def view_redirect(request, object_id): @require_POST def preview(request): data = request.POST.get('data', '') - markup = markdown.markdown(data, safe_mode=False, enable_attributes=False) + markup = markdown.markdown(data, safe_mode=True, enable_attributes=False) return HttpResponse(markup) # vim: set ts=4 sw=4 et: -- cgit v1.2.3-2-g168b From 563a618e697c918c2a76c63a5217047a8d3c1489 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Fri, 28 Dec 2012 10:12:09 -0600 Subject: Move slug creation helper to main/utils Signed-off-by: Dan McGee --- news/views.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'news/views.py') diff --git a/news/views.py b/news/views.py index 0e22ac34..62d30fde 100644 --- a/news/views.py +++ b/news/views.py @@ -3,26 +3,12 @@ import markdown from django import forms from django.http import HttpResponse from django.shortcuts import get_object_or_404, redirect -from django.template.defaultfilters import slugify from django.views.decorators.http import require_POST from django.views.generic import (DetailView, ListView, CreateView, UpdateView, DeleteView) from .models import News - - -def find_unique_slug(newsitem): - '''Attempt to find a unique slug for this news item.''' - existing = list(News.objects.values_list( - 'slug', flat=True).order_by().distinct()) - - suffixed = slug = slugify(newsitem.title) - suffix = 0 - while suffixed in existing: - suffix += 1 - suffixed = "%s-%d" % (slug, suffix) - - return suffixed +from main.utils import find_unique_slug class NewsForm(forms.ModelForm): @@ -51,7 +37,7 @@ class NewsCreateView(CreateView): # special logic, we auto-fill the author and slug fields newsitem = form.save(commit=False) newsitem.author = self.request.user - newsitem.slug = find_unique_slug(newsitem) + newsitem.slug = find_unique_slug(News, newsitem.title) newsitem.save() return super(NewsCreateView, self).form_valid(form) -- cgit v1.2.3-2-g168b From 1f126744417f40c1a27e8d53054b7bc588d12a00 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 16 Apr 2013 21:51:18 -0500 Subject: Grab author when loading news item details Saves a query to the database. Signed-off-by: Dan McGee --- news/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'news/views.py') diff --git a/news/views.py b/news/views.py index 62d30fde..ca4fdf97 100644 --- a/news/views.py +++ b/news/views.py @@ -18,7 +18,7 @@ class NewsForm(forms.ModelForm): class NewsDetailView(DetailView): - model = News + queryset = News.objects.all().select_related('author') template_name = "news/view.html" -- cgit v1.2.3-2-g168b