import pprint
import traceback
+from django.conf import settings
from django.template import RequestContext
from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect, Http404
if request.user.is_authenticated():
shelves = models.Tag.objects.filter(category='set', user=request.user)
new_set_form = forms.NewSetForm()
- extra_where = 'NOT catalogue_tag.category = "set"'
+ extra_where = "NOT catalogue_tag.category = 'set'"
tags = models.Tag.objects.usage_for_model(models.Book, counts=True, extra={'where': [extra_where]})
fragment_tags = models.Tag.objects.usage_for_model(models.Fragment, counts=True,
- extra={'where': ['catalogue_tag.category = "theme"'] + [extra_where]})
+ extra={'where': ["catalogue_tag.category = 'theme'"] + [extra_where]})
categories = split_tags(tags)
form = forms.SearchForm()
theme_is_set = len([tag for tag in tags if tag.category == 'theme']) > 0
if theme_is_set:
model = models.Fragment
+ only_author = len(tags) == 1 and tags[0].category == 'author'
+ pd_counter = only_author and tags[0].goes_to_pd()
user_is_owner = (len(shelf) and request.user.is_authenticated() and request.user == shelf[0].user)
- extra_where = 'catalogue_tag.category NOT IN ("set", "book")'
+ extra_where = "catalogue_tag.category NOT IN ('set', 'book')"
related_tags = models.Tag.objects.related_for_model(tags, model, counts=True, extra={'where': [extra_where]})
categories = split_tags(related_tags)
extra_context = {
'categories': categories,
'shelf_is_set': shelf_is_set,
+ 'only_author': only_author,
+ 'pd_counter': pd_counter,
'user_is_owner': user_is_owner,
'formats_form': forms.DownloadFormatsForm(),
},
def book_detail(request, slug):
- book = get_object_or_404(models.Book, slug=slug)
+ try:
+ book = models.Book.objects.get(slug=slug)
+ except models.Book.DoesNotExist:
+ return book_stub_detail(request, slug)
+
book_tag = get_object_or_404(models.Tag, slug = 'l-' + slug)
tags = list(book.tags.filter(~Q(category='set')))
categories = split_tags(tags)
book_children = book.children.all().order_by('parent_number')
- extra_where = 'catalogue_tag.category = "theme"'
+ extra_where = "catalogue_tag.category = 'theme'"
book_themes = models.Tag.objects.related_for_model(book_tag, models.Fragment, counts=True, extra={'where': [extra_where]})
extra_info = book.get_extra_info_value()
context_instance=RequestContext(request))
+def book_stub_detail(request, slug):
+ book = get_object_or_404(models.BookStub, slug=slug)
+ pd_counter = book.pd
+ form = forms.SearchForm()
+
+ return render_to_response('catalogue/book_stub_detail.html', locals(),
+ context_instance=RequestContext(request))
+
+
def book_text(request, slug):
book = get_object_or_404(models.Book, slug=slug)
book_themes = {}
# ==========
# = Search =
# ==========
+def _word_starts_with(name, prefix):
+ """returns a Q object gettings models having `name` contain a word
+ starting with `prefix`
+ """
+ kwargs = {}
+ if settings.DATABASE_ENGINE in ('mysql', 'postgresql_psycopg2', 'postgresql'):
+ # we must escape `prefix` so that it only matches literally
+ for special in r'\^$.*+?|(){}[]':
+ prefix = prefix.replace(special, '\\' + special)
+
+ # we could use a [[:<:]] (word start),
+ # but we want both `xy` and `(xy` to catch `(xyz)`
+ kwargs['%s__iregex' % name] = u"(^|[^[:alpha:]])%s" % prefix
+ else:
+ # don't know how to do a generic regex
+ # checking for simple icontain instead
+ kwargs['%s__icontains' % name] = prefix
+ return Q(**kwargs)
+
+
def _tags_starting_with(prefix, user):
- books = models.Book.objects.filter(title__icontains=prefix)
- tags = models.Tag.objects.filter(name__icontains=prefix)
+ book_stubs = models.BookStub.objects.filter(_word_starts_with('title', prefix))
+ books = models.Book.objects.filter(_word_starts_with('title', prefix))
+ book_stubs = filter(lambda x: x not in books, book_stubs)
+ tags = models.Tag.objects.filter(_word_starts_with('name', prefix))
if user.is_authenticated():
tags = tags.filter(~Q(category='book') & (~Q(category='set') | Q(user=user)))
else:
tags = tags.filter(~Q(category='book') & ~Q(category='set'))
- return list(books) + list(tags)
+ return list(books) + list(tags) + list(book_stubs)
def search(request):
result = _tags_starting_with(prefix, request.user)
if len(result) > 0:
tag = result[0]
- if isinstance(tag, models.Book):
+ if isinstance(tag, models.Book) or isinstance(tag, models.BookStub):
return HttpResponseRedirect(tag.get_absolute_url())
else:
tag_list.append(tag)
-
- return HttpResponseRedirect(reverse('catalogue.views.tagged_object_list',
- kwargs={'tags': '/'.join(tag.slug for tag in tag_list)}
- ))
+
+ return HttpResponseRedirect(reverse('catalogue.views.tagged_object_list',
+ kwargs={'tags': '/'.join(tag.slug for tag in tag_list)}
+ ))
+ else:
+ return render_to_response('catalogue/search_no_hits.html', {'query':prefix, 'tags':tag_list},
+ context_instance=RequestContext(request))
def tags_starting_with(request):
return HttpResponse("An error occurred: %s\n\n%s" % (exception, tb), mimetype='text/plain')
return HttpResponse("Book imported successfully")
else:
- return HttpResponse("Error importing file: %r" % book_import_form.errors)
\ No newline at end of file
+ return HttpResponse("Error importing file: %r" % book_import_form.errors)
+
+
+
+def clock(request):
+ """ Provides server time for jquery.countdown,
+ in a format suitable for Date.parse()
+ """
+ from datetime import datetime
+ return HttpResponse(datetime.now().strftime('%Y/%m/%d %H:%M:%S'))