evorepo/todolists/views.py
Dan McGee a5f5557493 Use python json module directly in place of simplejson
As of Python 2.6, this is a builtin module that has all the same
functions and capabilities of the Django simplejson module. Additionally
simplejson is deprecated in the upcoming Django 1.5 release.

Signed-off-by: Dan McGee <dan@archlinux.org>
2012-05-12 09:32:30 -05:00

190 lines
6.8 KiB
Python

import json
from django import forms
from django.http import HttpResponse
from django.core.mail import send_mail
from django.shortcuts import get_list_or_404, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required, permission_required
from django.db import transaction
from django.views.decorators.cache import never_cache
from django.views.generic import DeleteView
from django.views.generic.simple import direct_to_template
from django.template import Context, loader
from main.models import Todolist, TodolistPkg, Package, Repo
from packages.utils import attach_maintainers
from .utils import get_annotated_todolists
class TodoListForm(forms.ModelForm):
packages = forms.CharField(required=False,
help_text='(one per line)',
widget=forms.Textarea(attrs={'rows': '20', 'cols': '60'}))
def clean_packages(self):
package_names = [s.strip() for s in
self.cleaned_data['packages'].split("\n")]
package_names = set(package_names)
packages = Package.objects.filter(pkgname__in=package_names).filter(
repo__testing=False, repo__staging=False).select_related(
'arch', 'repo').order_by('arch')
return packages
class Meta:
model = Todolist
fields = ('name', 'description')
@permission_required('main.change_todolistpkg')
@never_cache
def flag(request, list_id, pkg_id):
todolist = get_object_or_404(Todolist, id=list_id)
pkg = get_object_or_404(TodolistPkg, id=pkg_id)
pkg.complete = not pkg.complete
pkg.save()
if request.is_ajax():
return HttpResponse(
json.dumps({'complete': pkg.complete}),
mimetype='application/json')
return redirect(todolist)
@login_required
def view(request, list_id):
todolist = get_object_or_404(Todolist, id=list_id)
svn_roots = Repo.objects.values_list(
'svn_root', flat=True).order_by().distinct()
# we don't hold onto the result, but the objects are the same here,
# so accessing maintainers in the template is now cheap
attach_maintainers(tp.pkg for tp in todolist.packages)
return direct_to_template(request, 'todolists/view.html', {
'list': todolist,
'svn_roots': svn_roots,
})
# really no need for login_required on this one...
def list_pkgbases(request, list_id, svn_root):
'''Used to make bulk moves of packages a lot easier.'''
todolist = get_object_or_404(Todolist, id=list_id)
repos = get_list_or_404(Repo, svn_root=svn_root)
pkgbases = set(tp.pkg.pkgbase for tp in todolist.packages
if tp.pkg.repo in repos)
return HttpResponse('\n'.join(sorted(pkgbases)),
mimetype='text/plain')
@login_required
def todolist_list(request):
lists = get_annotated_todolists()
return direct_to_template(request, 'todolists/list.html', {'lists': lists})
@permission_required('main.add_todolist')
@never_cache
def add(request):
if request.POST:
form = TodoListForm(request.POST)
if form.is_valid():
new_packages = create_todolist_packages(form, creator=request.user)
send_todolist_emails(form.instance, new_packages)
return redirect(form.instance)
else:
form = TodoListForm()
page_dict = {
'title': 'Add Todo List',
'form': form,
'submit_text': 'Create List'
}
return direct_to_template(request, 'general_form.html', page_dict)
# TODO: this calls for transaction management and async emailing
@permission_required('main.change_todolist')
@never_cache
def edit(request, list_id):
todo_list = get_object_or_404(Todolist, id=list_id)
if request.POST:
form = TodoListForm(request.POST, instance=todo_list)
if form.is_valid():
new_packages = create_todolist_packages(form)
send_todolist_emails(todo_list, new_packages)
return redirect(todo_list)
else:
form = TodoListForm(instance=todo_list,
initial={ 'packages': '\n'.join(todo_list.package_names) })
page_dict = {
'title': 'Edit Todo List: %s' % todo_list.name,
'form': form,
'submit_text': 'Save List'
}
return direct_to_template(request, 'general_form.html', page_dict)
class DeleteTodolist(DeleteView):
model = Todolist
# model in main == assumes name 'main/todolist_confirm_delete.html'
template_name = 'todolists/todolist_confirm_delete.html'
success_url = '/todo/'
@transaction.commit_on_success
def create_todolist_packages(form, creator=None):
packages = form.cleaned_data['packages']
if creator:
# todo list is new
todolist = form.save(commit=False)
todolist.creator = creator
todolist.save()
old_packages = []
else:
# todo list already existed
form.save()
todolist = form.instance
# first delete any packages not in the new list
for todo_pkg in todolist.packages:
if todo_pkg.pkg not in packages:
todo_pkg.delete()
# save the old package list so we know what to add
old_packages = [p.pkg for p in todolist.packages]
todo_pkgs = []
for package in packages:
if package not in old_packages:
todo_pkg = TodolistPkg.objects.create(list=todolist, pkg=package)
todo_pkgs.append(todo_pkg)
return todo_pkgs
def send_todolist_emails(todo_list, new_packages):
'''Sends emails to package maintainers notifying them that packages have
been added to a todo list.'''
# start by flipping the incoming list on its head: we want a list of
# involved maintainers and the packages they need to be notified about.
orphan_packages = []
maint_packages = {}
for todo_package in new_packages:
maints = todo_package.pkg.maintainers.values_list('email', flat=True)
if not maints:
orphan_packages.append(todo_package)
else:
for maint in maints:
maint_packages.setdefault(maint, []).append(todo_package)
for maint, packages in maint_packages.iteritems():
ctx = Context({
'todo_packages': sorted(packages),
'todolist': todo_list,
})
template = loader.get_template('todolists/email_notification.txt')
send_mail('Packages added to todo list \'%s\'' % todo_list.name,
template.render(ctx),
'Arch Website Notification <nobody@archlinux.org>',
[maint],
fail_silently=True)
def public_list(request):
todo_lists = Todolist.objects.incomplete()
# total hackjob, but it makes this a lot less query-intensive.
all_pkgs = [tp for tl in todo_lists for tp in tl.packages]
attach_maintainers([tp.pkg for tp in all_pkgs])
return direct_to_template(request, "todolists/public_list.html",
{"todo_lists": todo_lists})
# vim: set ts=4 sw=4 et: