Пример #1
0
def posts(request, forum_slug, thread_id, form=None, reply_preview=None):
    """View all the posts in a thread."""
    forum = get_object_or_404(Forum, slug=forum_slug)
    if not forum.allows_viewing_by(request.user):
        raise Http404

    thread = get_object_or_404(Thread, pk=thread_id, forum=forum)

    posts_ = paginate(request, thread.post_set.all(), constants.POSTS_PER_PAGE)

    if not form:
        form = ReplyForm()

    feed_urls = ((reverse('forums.posts.feed',
                          kwargs={
                              'forum_slug': forum_slug,
                              'thread_id': thread_id
                          }), PostsFeed().title(thread)), )

    is_watching_thread = (request.user.is_authenticated()
                          and NewPostEvent.is_notifying(request.user, thread))
    return jingo.render(
        request, 'forums/posts.html', {
            'forum': forum,
            'thread': thread,
            'posts': posts_,
            'form': form,
            'reply_preview': reply_preview,
            'is_watching_thread': is_watching_thread,
            'feeds': feed_urls,
            'forums': Forum.objects.all()
        })
Пример #2
0
def threads(request, document_slug):
    """View all the threads in a discussion forum."""
    doc = get_document(document_slug, request)
    try:
        sort = int(request.GET.get('sort', 0))
    except ValueError:
        sort = 0

    try:
        desc = int(request.GET.get('desc', 0))
    except ValueError:
        desc = 0
    desc_toggle = 0 if desc else 1

    threads_ = sort_threads(doc.thread_set, sort, desc)
    threads_ = paginate(request, threads_, per_page=kbforums.THREADS_PER_PAGE)

    feed_urls = ((reverse('wiki.discuss.threads.feed',
                          args=[document_slug]), ThreadsFeed().title(doc)), )

    is_watching_forum = (request.user.is_authenticated()
                         and NewThreadEvent.is_notifying(request.user, doc))
    return jingo.render(
        request, 'kbforums/threads.html', {
            'document': doc,
            'threads': threads_,
            'is_watching_forum': is_watching_forum,
            'sort': sort,
            'desc_toggle': desc_toggle,
            'feeds': feed_urls
        })
Пример #3
0
def posts(request, forum_slug, thread_id, form=None, reply_preview=None):
    """View all the posts in a thread."""
    forum = get_object_or_404(Forum, slug=forum_slug)
    if not forum.allows_viewing_by(request.user):
        raise Http404

    thread = get_object_or_404(Thread, pk=thread_id, forum=forum)

    posts_ = paginate(request, thread.post_set.all(),
                      constants.POSTS_PER_PAGE)

    if not form:
        form = ReplyForm()

    feed_urls = ((reverse('forums.posts.feed',
                          kwargs={'forum_slug': forum_slug,
                                  'thread_id': thread_id}),
                  PostsFeed().title(thread)),)

    is_watching_thread = (request.user.is_authenticated() and
                          NewPostEvent.is_notifying(request.user, thread))
    return jingo.render(request, 'forums/posts.html',
                        {'forum': forum, 'thread': thread,
                         'posts': posts_, 'form': form,
                         'reply_preview': reply_preview,
                         'is_watching_thread': is_watching_thread,
                         'feeds': feed_urls,
                         'forums': Forum.objects.all()})
Пример #4
0
def test_invalid_page_param():
    url = '%s?%s' % (reverse('search'), 'page=a')
    request = test_utils.RequestFactory().get(url)
    queryset = range(100)
    paginated = paginate(request, queryset)
    eq_(paginated.url,
        request.build_absolute_uri(request.path) + '?')
Пример #5
0
def threads(request, forum_slug):
    """View all the threads in a forum."""
    forum = get_object_or_404(Forum, slug=forum_slug)
    if not forum.allows_viewing_by(request.user):
        raise Http404  # Pretend there's nothing there.

    try:
        sort = int(request.GET.get('sort', 0))
    except ValueError:
        sort = 0

    try:
        desc = int(request.GET.get('desc', 0))
    except ValueError:
        desc = 0
    desc_toggle = 0 if desc else 1

    threads_ = sort_threads(forum.thread_set, sort, desc)
    count = threads_.count()
    threads_ = threads_.select_related('creator', 'last_post',
                                       'last_post__author')
    threads_ = paginate(request, threads_,
                        per_page=constants.THREADS_PER_PAGE, count=count)

    feed_urls = ((reverse('forums.threads.feed', args=[forum_slug]),
                  ThreadsFeed().title(forum)),)

    is_watching_forum = (request.user.is_authenticated() and
                         NewThreadEvent.is_notifying(request.user, forum))
    return jingo.render(request, 'forums/threads.html',
                        {'forum': forum, 'threads': threads_,
                         'is_watching_forum': is_watching_forum,
                         'sort': sort, 'desc_toggle': desc_toggle,
                         'feeds': feed_urls})
Пример #6
0
def history(request, pk):
    key = get_object_or_404(Key, pk=pk)
    if key.user != request.user:
        raise PermissionDenied
    items = key.history.all().order_by('-pk')
    items = paginate(request, items, per_page=ITEMS_PER_PAGE)
    return render(request, 'authkeys/history.html', dict(key=key, items=items))
Пример #7
0
def posts(request, forum_slug, thread_id, form=None, reply_preview=None):
    """View all the posts in a thread."""
    forum = get_object_or_404(Forum, slug=forum_slug)
    if not forum.allows_viewing_by(request.user):
        raise Http404

    thread = get_object_or_404(Thread, pk=thread_id, forum=forum)

    posts_ = thread.post_set.all()
    count = posts_.count()
    posts_ = posts_.select_related('author', 'updated_by')
    posts_ = posts_.extra(
        select={'author_post_count': 'SELECT COUNT(*) FROM forums_post WHERE '
                                     'forums_post.author_id = auth_user.id'})
    posts_ = paginate(request, posts_, constants.POSTS_PER_PAGE, count=count)

    if not form:
        form = ReplyForm()

    feed_urls = ((reverse('forums.posts.feed',
                          kwargs={'forum_slug': forum_slug,
                                  'thread_id': thread_id}),
                  PostsFeed().title(thread)),)

    is_watching_thread = (request.user.is_authenticated() and
                          NewPostEvent.is_notifying(request.user, thread))
    return jingo.render(request, 'forums/posts.html',
                        {'forum': forum, 'thread': thread,
                         'posts': posts_, 'form': form,
                         'reply_preview': reply_preview,
                         'is_watching_thread': is_watching_thread,
                         'feeds': feed_urls,
                         'forums': Forum.objects.all()})
Пример #8
0
def gallery_async(request):
    """AJAX endpoint to media gallery.

    Returns an HTML list representation of the media.

    """
    # Maybe refactor this into existing views and check request.is_ajax?
    media_type = request.GET.get('type', 'image')
    term = request.GET.get('q')
    if media_type == 'image':
        media_qs = Image.objects
    elif media_type == 'video':
        media_qs = Video.objects
    else:
        raise Http404

    if request.LANGUAGE_CODE == settings.WIKI_DEFAULT_LANGUAGE:
        media_qs = media_qs.filter(locale=request.LANGUAGE_CODE)
    else:
        locales = [request.LANGUAGE_CODE, settings.WIKI_DEFAULT_LANGUAGE]
        media_qs = media_qs.filter(locale__in=locales)

    if term:
        media_qs = media_qs.filter(Q(title__icontains=term) |
                                   Q(description__icontains=term))

    media = paginate(request, media_qs, per_page=ITEMS_PER_PAGE)

    return jingo.render(request, 'gallery/includes/media_list.html',
                        {'media_list': media})
Пример #9
0
def _answers_data(request, question_id, form=None, watch_form=None,
                  answer_preview=None):
    """Return a map of the minimal info necessary to draw an answers page."""
    question = get_object_or_404(Question, pk=question_id)
    answers_ = paginate(request, question.answers.all(),
                        per_page=constants.ANSWERS_PER_PAGE)
    vocab = [t.name for t in Tag.objects.all()]  # TODO: Fetch only name.
    feed_urls = ((reverse('questions.answers.feed',
                          kwargs={'question_id': question_id}),
                  AnswersFeed().title(question)),)
    frequencies = dict(FREQUENCY_CHOICES)

    is_watching_question = (
        request.user.is_authenticated() and (
        QuestionReplyEvent.is_notifying(request.user, question) or
        QuestionSolvedEvent.is_notifying(request.user, question)))
    return {'question': question,
            'answers': answers_,
            'form': form or AnswerForm(),
            'answer_preview': answer_preview,
            'watch_form': watch_form or _init_watch_form(request, 'reply'),
            'feeds': feed_urls,
            'tag_vocab': json.dumps(vocab),
            'frequencies': frequencies,
            'is_watching_question': is_watching_question,
            'can_tag': request.user.has_perm('questions.tag_question'),
            'can_create_tags': request.user.has_perm('taggit.add_tag')}
Пример #10
0
def _answers_data(request, question_id, form=None, watch_form=None, answer_preview=None):
    """Return a map of the minimal info necessary to draw an answers page."""
    question = get_object_or_404(Question, pk=question_id)
    answers_ = paginate(request, question.answers.all(), per_page=constants.ANSWERS_PER_PAGE)
    vocab = [t.name for t in Tag.objects.all()]  # TODO: Fetch only name.
    feed_urls = (
        (reverse("questions.answers.feed", kwargs={"question_id": question_id}), AnswersFeed().title(question)),
    )
    frequencies = dict(FREQUENCY_CHOICES)

    is_watching_question = request.user.is_authenticated() and (
        QuestionReplyEvent.is_notifying(request.user, question)
        or QuestionSolvedEvent.is_notifying(request.user, question)
    )
    return {
        "question": question,
        "answers": answers_,
        "form": form or AnswerForm(),
        "answer_preview": answer_preview,
        "watch_form": watch_form or _init_watch_form(request, "reply"),
        "feeds": feed_urls,
        "tag_vocab": json.dumps(vocab),
        "frequencies": frequencies,
        "is_watching_question": is_watching_question,
        "can_tag": request.user.has_perm("questions.tag_question"),
        "can_create_tags": request.user.has_perm("taggit.add_tag"),
    }
Пример #11
0
def locale_discussions(request):
    locale_name = LOCALES[request.LANGUAGE_CODE].native
    threads = Thread.objects.filter(document__locale=request.LANGUAGE_CODE,
                                    document__allow_discussion=True)
    try:
        sort = int(request.GET.get('sort', 0))
    except ValueError:
        sort = 0

    try:
        desc = int(request.GET.get('desc', 0))
    except ValueError:
        desc = 0
    desc_toggle = 0 if desc else 1

    threads_ = sort_threads(threads, sort, desc)

    # Ignore sticky-ness:
    threads_ = threads_.order_by('-last_post__created')
    threads_ = paginate(request, threads_, per_page=kbforums.THREADS_PER_PAGE)
    is_watching_locale = (request.user.is_authenticated()
                          and NewThreadInLocaleEvent.is_notifying(
                              request.user, locale=request.LANGUAGE_CODE))
    return render(
        request, 'kbforums/discussions.html', {
            'locale_name': locale_name,
            'threads': threads_,
            'desc_toggle': desc_toggle,
            'is_watching_locale': is_watching_locale
        })
Пример #12
0
def gallery(request, media_type="image"):
    """The media gallery.

    Filter can be set to 'images' or 'videos'.

    """
    if media_type == "image":
        media_qs = Image.objects.filter(locale=request.locale)
    elif media_type == "video":
        media_qs = Video.objects.filter(locale=request.locale)
    else:
        raise Http404

    media = paginate(request, media_qs, per_page=ITEMS_PER_PAGE)

    drafts = _get_drafts(request.user)
    image_form, video_form, upload_type_form = _init_forms(request, drafts)

    return jingo.render(
        request,
        "gallery/gallery.html",
        {
            "media": media,
            "media_type": media_type,
            "upload_type_form": upload_type_form,
            "image_form": image_form,
            "video_form": video_form,
        },
    )
Пример #13
0
def threads(request, document_slug):
    """View all the threads in a discussion forum."""
    doc = get_document(document_slug, request)
    try:
        sort = int(request.GET.get('sort', 0))
    except ValueError:
        sort = 0

    try:
        desc = int(request.GET.get('desc', 0))
    except ValueError:
        desc = 0
    desc_toggle = 0 if desc else 1

    threads_ = sort_threads(doc.thread_set, sort, desc)
    threads_ = paginate(request, threads_,
                        per_page=kbforums.THREADS_PER_PAGE)

    feed_urls = ((reverse('wiki.discuss.threads.feed', args=[document_slug]),
                  ThreadsFeed().title(doc)),)

    is_watching_forum = (request.user.is_authenticated() and
                         NewThreadEvent.is_notifying(request.user, doc))
    return jingo.render(request, 'kbforums/threads.html',
                        {'document': doc, 'threads': threads_,
                         'is_watching_forum': is_watching_forum,
                         'sort': sort, 'desc_toggle': desc_toggle,
                         'feeds': feed_urls})
Пример #14
0
def locale_discussions(request):
    locale_name = LOCALES[request.LANGUAGE_CODE].native
    threads = Thread.objects.filter(document__locale=request.LANGUAGE_CODE,
                                    document__allow_discussion=True)
    try:
        sort = int(request.GET.get('sort', 0))
    except ValueError:
        sort = 0

    try:
        desc = int(request.GET.get('desc', 0))
    except ValueError:
        desc = 0
    desc_toggle = 0 if desc else 1

    threads_ = sort_threads(threads, sort, desc)

    # Ignore sticky-ness:
    threads_ = threads_.order_by('-last_post__created')
    threads_ = paginate(request, threads_,
                        per_page=kbforums.THREADS_PER_PAGE)
    is_watching_locale = (request.user.is_authenticated() and
                          NewThreadInLocaleEvent.is_notifying(
                            request.user, locale=request.LANGUAGE_CODE))
    return render(request, 'kbforums/discussions.html', {
        'locale_name': locale_name, 'threads': threads_,
        'desc_toggle': desc_toggle,
        'is_watching_locale': is_watching_locale})
Пример #15
0
def posts(request, document_slug, thread_id, form=None, reply_preview=None):
    """View all the posts in a thread."""
    doc = get_document(document_slug, request)

    thread = get_object_or_404(Thread, pk=thread_id, document=doc)

    posts_ = paginate(request, thread.post_set.all(),
                      kbforums.POSTS_PER_PAGE)

    if not form:
        form = ReplyForm()

    feed_urls = ((reverse('wiki.discuss.posts.feed',
                          kwargs={'document_slug': document_slug,
                                  'thread_id': thread_id}),
                  PostsFeed().title(thread)),)

    is_watching_thread = (request.user.is_authenticated() and
                          NewPostEvent.is_notifying(request.user, thread))
    return jingo.render(request, 'kbforums/posts.html',
                        {'document': doc, 'thread': thread,
                         'posts': posts_, 'form': form,
                         'reply_preview': reply_preview,
                         'is_watching_thread': is_watching_thread,
                         'feeds': feed_urls})
Пример #16
0
def threads(request, document_slug):
    """View all the threads in a discussion forum."""
    doc = get_document(document_slug, request)
    try:
        sort = int(request.GET.get("sort", 0))
    except ValueError:
        sort = 0

    try:
        desc = int(request.GET.get("desc", 0))
    except ValueError:
        desc = 0
    desc_toggle = 0 if desc else 1

    threads_ = sort_threads(doc.thread_set, sort, desc)
    threads_ = paginate(request, threads_, per_page=kbforums.THREADS_PER_PAGE)

    feed_urls = ((reverse("wiki.discuss.threads.feed", args=[document_slug]), ThreadsFeed().title(doc)),)

    is_watching_forum = request.user.is_authenticated() and NewThreadEvent.is_notifying(request.user, doc)
    return jingo.render(
        request,
        "kbforums/threads.html",
        {
            "document": doc,
            "threads": threads_,
            "is_watching_forum": is_watching_forum,
            "sort": sort,
            "desc_toggle": desc_toggle,
            "feeds": feed_urls,
        },
    )
Пример #17
0
def locale_discussions(request):
    locale_name = LOCALES[request.locale].native
    threads = Thread.objects.filter(document__locale=request.locale, document__allow_discussion=True)
    try:
        sort = int(request.GET.get("sort", 0))
    except ValueError:
        sort = 0

    try:
        desc = int(request.GET.get("desc", 0))
    except ValueError:
        desc = 0
    desc_toggle = 0 if desc else 1

    threads_ = sort_threads(threads, sort, desc)

    # Ignore sticky-ness:
    threads_ = threads_.order_by("-last_post__created")
    threads_ = paginate(request, threads_, per_page=kbforums.THREADS_PER_PAGE)
    is_watching_locale = request.user.is_authenticated() and NewThreadInLocaleEvent.is_notifying(
        request.user, locale=request.locale
    )
    return jingo.render(
        request,
        "kbforums/discussions.html",
        {
            "locale_name": locale_name,
            "threads": threads_,
            "desc_toggle": desc_toggle,
            "is_watching_locale": is_watching_locale,
        },
    )
Пример #18
0
def _answers_data(request, question_id, form=None, watch_form=None,
                  answer_preview=None):
    """Return a map of the minimal info necessary to draw an answers page."""
    question = get_object_or_404(Question, pk=question_id)
    answers_ = question.answers.all()
    if not request.MOBILE:
        answers_ = paginate(request, answers_,
                            per_page=constants.ANSWERS_PER_PAGE)
    feed_urls = ((reverse('questions.answers.feed',
                          kwargs={'question_id': question_id}),
                  AnswersFeed().title(question)),)
    frequencies = dict(FREQUENCY_CHOICES)

    is_watching_question = (
        request.user.is_authenticated() and (
        QuestionReplyEvent.is_notifying(request.user, question) or
        QuestionSolvedEvent.is_notifying(request.user, question)))
    return {'question': question,
            'answers': answers_,
            'form': form or AnswerForm(),
            'answer_preview': answer_preview,
            'watch_form': watch_form or _init_watch_form(request, 'reply'),
            'feeds': feed_urls,
            'frequencies': frequencies,
            'is_watching_question': is_watching_question,
            'can_tag': request.user.has_perm('questions.tag_question'),
            'can_create_tags': request.user.has_perm('taggit.add_tag')}
Пример #19
0
def list_documents(request, category=None, tag=None):
    """List wiki documents."""
    docs = Document.objects.filter(locale=request.locale).order_by('title')
    if category:
        docs = docs.filter(category=category)
        try:
            category_id = int(category)
        except ValueError:
            raise Http404
        try:
            category = unicode(dict(CATEGORIES)[category_id])
        except KeyError:
            raise Http404

    if tag:
        tagobj = get_object_or_404(Tag, slug=tag)
        default_lang = settings.WIKI_DEFAULT_LANGUAGE
        if request.locale == default_lang:
            docs = docs.filter(tags__name=tagobj.name)
        else:
            # blows up: docs = docs.filter(parent__tags__name=tagobj.name)
            parent_ids = Document.objects.filter(
                locale=default_lang, tags__name=tagobj.name) \
                .values_list('id', flat=True)
            docs = docs.filter(parent__in=parent_ids)

    docs = paginate(request, docs, per_page=DOCUMENTS_PER_PAGE)
    return jingo.render(request, 'wiki/list_documents.html',
                        {'documents': docs,
                         'category': category,
                         'tag': tag})
Пример #20
0
def forums(request):
    """View all the forums."""
    forums_ = [
        f for f in Forum.objects.all() if f.allows_viewing_by(request.user)
    ]
    return jingo.render(request, 'forums/forums.html',
                        {'forums': paginate(request, forums_)})
Пример #21
0
def questions(request):
    """View the questions."""

    filter = request.GET.get('filter')
    tagged = request.GET.get('tagged')
    tags = None
    sort_ = request.GET.get('sort')

    if sort_ == 'requested':
        order = '-num_votes_past_week'
    else:
        sort_ = None
        order = '-updated'

    question_qs = Question.objects.filter(creator__is_active=1,
                                          status=CONFIRMED)
    if filter == 'no-replies':
        question_qs = question_qs.filter(num_answers=0)
    elif filter == 'replies':
        question_qs = question_qs.filter(num_answers__gt=0)
    elif filter == 'solved':
        question_qs = question_qs.exclude(solution=None)
    elif filter == 'unsolved':
        question_qs = question_qs.filter(solution=None)
    elif filter == 'my-contributions' and request.user.is_authenticated():
        criteria = Q(answers__creator=request.user) | Q(creator=request.user)
        question_qs = question_qs.filter(criteria).distinct()
    else:
        filter = None

    feed_urls = ((reverse('questions.feed'), QuestionsFeed().title()), )

    if tagged:
        tag_slugs = tagged.split(',')
        tags = Tag.objects.filter(slug__in=tag_slugs)
        if tags:
            for t in tags:
                question_qs = question_qs.filter(tags__name__in=[t.name])
            if len(tags) == 1:
                feed_urls += ((reverse('questions.tagged_feed',
                                       args=[tags[0].slug]),
                               TaggedQuestionsFeed().title(tags[0])), )
        else:
            question_qs = Question.objects.get_empty_query_set()

    question_qs = question_qs.order_by(order)
    questions_ = paginate(request,
                          question_qs,
                          per_page=constants.QUESTIONS_PER_PAGE)

    return jingo.render(
        request, 'questions/questions.html', {
            'questions': questions_,
            'feeds': feed_urls,
            'filter': filter,
            'sort': sort_,
            'top_contributors': _get_top_contributors(),
            'tags': tags,
            'tagged': tagged
        })
Пример #22
0
def list_documents(request, category=None, topic=None):
    """List wiki documents."""
    docs = Document.objects.filter(locale=request.LANGUAGE_CODE).order_by('title')
    if category:
        docs = docs.filter(category=category)
        try:
            category_id = int(category)
        except ValueError:
            raise Http404
        try:
            category = unicode(dict(CATEGORIES)[category_id])
        except KeyError:
            raise Http404

    if topic:
        topic = get_object_or_404(Topic, slug=topic)
        default_lang = settings.WIKI_DEFAULT_LANGUAGE
        if request.LANGUAGE_CODE == default_lang:
            docs = docs.filter(topics=topic)
        else:
            parent_ids = Document.objects.filter(
                locale=default_lang, topics=topic).values_list('id', flat=True)
            docs = docs.filter(parent__in=parent_ids)

    docs = paginate(request, docs, per_page=DOCUMENTS_PER_PAGE)
    return render(request, 'wiki/list_documents.html', {
        'documents': docs,
        'category': category,
        'topic': topic.title if topic else None})
Пример #23
0
def posts(request, document_slug, thread_id, form=None, reply_preview=None):
    """View all the posts in a thread."""
    doc = get_document(document_slug, request)

    thread = get_object_or_404(Thread, pk=thread_id, document=doc)

    posts_ = paginate(request, thread.post_set.all(), kbforums.POSTS_PER_PAGE)

    if not form:
        form = ReplyForm()

    feed_urls = ((reverse('wiki.discuss.posts.feed',
                          kwargs={
                              'document_slug': document_slug,
                              'thread_id': thread_id
                          }), PostsFeed().title(thread)), )

    is_watching_thread = (request.user.is_authenticated()
                          and NewPostEvent.is_notifying(request.user, thread))
    return jingo.render(
        request, 'kbforums/posts.html', {
            'document': doc,
            'thread': thread,
            'posts': posts_,
            'form': form,
            'reply_preview': reply_preview,
            'is_watching_thread': is_watching_thread,
            'feeds': feed_urls
        })
Пример #24
0
def list_documents(request, category=None, topic=None):
    """List wiki documents."""
    docs = Document.objects.filter(locale=request.locale).order_by('title')
    if category:
        docs = docs.filter(category=category)
        try:
            category_id = int(category)
        except ValueError:
            raise Http404
        try:
            category = unicode(dict(CATEGORIES)[category_id])
        except KeyError:
            raise Http404

    if topic:
        topic = get_object_or_404(Topic, slug=topic)
        default_lang = settings.WIKI_DEFAULT_LANGUAGE
        if request.locale == default_lang:
            docs = docs.filter(topics=topic)
        else:
            parent_ids = Document.objects.filter(locale=default_lang,
                                                 topics=topic).values_list(
                                                     'id', flat=True)
            docs = docs.filter(parent__in=parent_ids)

    docs = paginate(request, docs, per_page=DOCUMENTS_PER_PAGE)
    return jingo.render(
        request, 'wiki/list_documents.html', {
            'documents': docs,
            'category': category,
            'topic': topic.title if topic else None
        })
Пример #25
0
def posts(request,
          forum_slug,
          thread_id,
          form=None,
          post_preview=None,
          is_reply=False):
    """View all the posts in a thread."""
    thread = get_object_or_404(Thread, pk=thread_id)
    forum = thread.forum

    if forum.slug != forum_slug and not is_reply:
        new_forum = get_object_or_404(Forum, slug=forum_slug)
        if new_forum.allows_viewing_by(request.user):
            return HttpResponseRedirect(thread.get_absolute_url())
        raise Http404  # User has no right to view destination forum.
    elif forum.slug != forum_slug:
        raise Http404

    if not forum.allows_viewing_by(request.user):
        raise Http404

    posts_ = thread.post_set.all()
    count = posts_.count()
    if count:
        last_post = posts_[count - 1]
    else:
        last_post = None
    posts_ = posts_.select_related('author', 'updated_by')
    posts_ = posts_.extra(
        select={
            'author_post_count':
            'SELECT COUNT(*) FROM forums_post WHERE '
            'forums_post.author_id = auth_user.id'
        })
    posts_ = paginate(request, posts_, constants.POSTS_PER_PAGE, count=count)

    if not form:
        form = ReplyForm()

    feed_urls = ((reverse('forums.posts.feed',
                          kwargs={
                              'forum_slug': forum_slug,
                              'thread_id': thread_id
                          }), PostsFeed().title(thread)), )

    is_watching_thread = (request.user.is_authenticated()
                          and NewPostEvent.is_notifying(request.user, thread))
    return render(
        request, 'forums/posts.html', {
            'forum': forum,
            'thread': thread,
            'posts': posts_,
            'form': form,
            'count': count,
            'last_post': last_post,
            'post_preview': post_preview,
            'is_watching_thread': is_watching_thread,
            'feeds': feed_urls,
            'forums': Forum.objects.all()
        })
Пример #26
0
def test_invalid_page_param():
    url = '%s?%s' % (reverse('search'), 'page=a')
    request = test_utils.RequestFactory().get(url)
    queryset = range(100)
    paginated = paginate(request, queryset)
    eq_(paginated.url,
        request.build_absolute_uri(request.path) + '?')
Пример #27
0
def gallery_async(request):
    """AJAX endpoint to media gallery.

    Returns an HTML list representation of the media.

    """
    # Maybe refactor this into existing views and check request.is_ajax?
    media_type = request.GET.get('type', 'image')
    term = request.GET.get('q')
    if media_type == 'image':
        media_qs = Image.objects
    elif media_type == 'video':
        media_qs = Video.objects
    else:
        raise Http404

    if request.locale == settings.WIKI_DEFAULT_LANGUAGE:
        media_qs = media_qs.filter(locale=request.locale)
    else:
        locales = [request.locale, settings.WIKI_DEFAULT_LANGUAGE]
        media_qs = media_qs.filter(locale__in=locales)

    if term:
        media_qs = media_qs.filter(
            Q(title__icontains=term) | Q(description__icontains=term))

    media = paginate(request, media_qs, per_page=ITEMS_PER_PAGE)

    return jingo.render(request, 'gallery/includes/media_list.html',
                        {'media_list': media})
Пример #28
0
def gallery(request, media_type='image'):
    """The media gallery.

    Filter can be set to 'images' or 'videos'.

    """
    if media_type == 'image':
        media_qs = Image.objects.filter(locale=request.locale)
    elif media_type == 'video':
        media_qs = Video.objects.filter(locale=request.locale)
    else:
        raise Http404

    media = paginate(request, media_qs, per_page=ITEMS_PER_PAGE)

    drafts = _get_drafts(request.user)
    image_form, video_form, upload_type_form = _init_forms(request, drafts)

    return jingo.render(
        request, 'gallery/gallery.html', {
            'media': media,
            'media_type': media_type,
            'upload_type_form': upload_type_form,
            'image_form': image_form,
            'video_form': video_form
        })
Пример #29
0
def posts(request, forum_slug, thread_id, form=None, reply_preview=None):
    """View all the posts in a thread."""
    forum = get_object_or_404(Forum, slug=forum_slug)
    if not forum.allows_viewing_by(request.user):
        raise Http404

    thread = get_object_or_404(Thread, pk=thread_id, forum=forum)

    posts_ = paginate(request, thread.post_set.all(), constants.POSTS_PER_PAGE)

    if not form:
        form = ReplyForm()

    feed_urls = (
        (
            reverse("forums.posts.feed", kwargs={"forum_slug": forum_slug, "thread_id": thread_id}),
            PostsFeed().title(thread),
        ),
    )

    return jingo.render(
        request,
        "forums/posts.html",
        {
            "forum": forum,
            "thread": thread,
            "posts": posts_,
            "form": form,
            "reply_preview": reply_preview,
            "feeds": feed_urls,
            "forums": Forum.objects.all(),
        },
    )
Пример #30
0
def threads(request, forum_slug):
    """View all the threads in a forum."""
    forum = get_object_or_404(Forum, slug=forum_slug)
    if not forum.allows_viewing_by(request.user):
        raise Http404  # Pretend there's nothing there.

    try:
        sort = int(request.GET.get("sort", 0))
    except ValueError:
        sort = 0

    try:
        desc = int(request.GET.get("desc", 0))
    except ValueError:
        desc = 0
    desc_toggle = 0 if desc else 1

    threads_ = sort_threads(forum.thread_set, sort, desc)
    threads_ = paginate(request, threads_, per_page=constants.THREADS_PER_PAGE)

    feed_urls = ((reverse("forums.threads.feed", args=[forum_slug]), ThreadsFeed().title(forum)),)

    return jingo.render(
        request,
        "forums/threads.html",
        {"forum": forum, "threads": threads_, "sort": sort, "desc_toggle": desc_toggle, "feeds": feed_urls},
    )
Пример #31
0
def test_paginated_url():
    """Avoid duplicating page param in pagination."""
    url = '%s?%s' % (reverse('search'), 'q=bookmarks&page=2')
    request = test_utils.RequestFactory().get(url)
    queryset = [{}, {}]
    paginated = paginate(request, queryset)
    eq_(paginated.url,
        request.build_absolute_uri(request.path) + '?q=bookmarks')
Пример #32
0
def test_paginator_filter():

    # Correct number of <li>s on page 1.
    url = reverse('search')
    request = test_utils.RequestFactory().get(url)
    pager = paginate(request, range(100), per_page=9)
    html = paginator(pager)
    doc = pyquery.PyQuery(html)
    eq_(11, len(doc('li')))

    # Correct number of <li>s in the middle.
    url = '%s?%s' % (reverse('search'), 'page=10')
    request = test_utils.RequestFactory().get(url)
    pager = paginate(request, range(200), per_page=10)
    html = paginator(pager)
    doc = pyquery.PyQuery(html)
    eq_(13, len(doc('li')))
Пример #33
0
def test_paginated_url():
    """Avoid duplicating page param in pagination."""
    url = '%s?%s' % (reverse('search'), 'q=bookmarks&page=2')
    request = test_utils.RequestFactory().get(url)
    queryset = [{}, {}]
    paginated = paginate(request, queryset)
    eq_(paginated.url,
        request.build_absolute_uri(request.path) + '?q=bookmarks')
Пример #34
0
def history(request, pk):
    key = get_object_or_404(Key, pk=pk)
    if key.user != request.user:
        raise PermissionDenied
    items = key.history.all().order_by('-pk')
    items = paginate(request, items, per_page=ITEMS_PER_PAGE)
    return jingo.render(request, 'authkeys/history.html',
                        dict(key=key, items=items))
Пример #35
0
def test_paginator_filter():

    # Correct number of <li>s on page 1.
    url = reverse('search')
    request = test_utils.RequestFactory().get(url)
    pager = paginate(request, range(100), per_page=9)
    html = paginator(pager)
    doc = pyquery.PyQuery(html)
    eq_(11, len(doc('li')))

    # Correct number of <li>s in the middle.
    url = '%s?%s' % (reverse('search'), 'page=10')
    request = test_utils.RequestFactory().get(url)
    pager = paginate(request, range(200), per_page=10)
    html = paginator(pager)
    doc = pyquery.PyQuery(html)
    eq_(13, len(doc('li')))
Пример #36
0
def revisions(request):
    """Dashboard for reviewing revisions"""

    filter_form = RevisionDashboardForm(request.GET)
    page = request.GET.get('page', 1)

    revisions = (Revision.objects.select_related('creator')
                        .order_by('-created')
                        .defer('content'))

    query_kwargs = False

    # We can validate right away because no field is required
    if filter_form.is_valid():
        query_kwargs = {}
        query_kwargs_map = {
            'user': '******',
            'locale': 'document__locale',
            'topic': 'slug__icontains',
        }

        # Build up a dict of the filter conditions, if any, then apply
        # them all in one go.
        for fieldname, kwarg in query_kwargs_map.items():
            filter_arg = filter_form.cleaned_data[fieldname]
            if filter_arg:
                query_kwargs[kwarg] = filter_arg

        start_date = filter_form.cleaned_data['start_date']
        if start_date:
            end_date = (filter_form.cleaned_data['end_date'] or
                                datetime.datetime.now())
            query_kwargs['created__range'] = [start_date, end_date]

    if query_kwargs:
        revisions = revisions.filter(**query_kwargs)
        total = revisions.count()
    else:
        # If no filters, just do a straight count(). It's the same
        # result, but much faster to compute.
        total = Revision.objects.count()

    # Only bother with this if we're actually going to get
    # some revisions from it. Otherwise it's a pointless but
    # potentially complex query.
    revisions = paginate(request, revisions, per_page=PAGE_SIZE)

    context = {'revisions': revisions, 'page': page, 'total': total}

    # Serve the response HTML conditionally upon reques type
    if request.is_ajax():
        return render(request,
            'dashboards/includes/revision_dashboard_body.html',
            context)
    else:
        context['form'] = filter_form

    return render(request, 'dashboards/revisions.html', context)
Пример #37
0
def forums(request):
    """View all the forums."""
    qs = Forum.objects.select_related('last_post', 'last_post__author')
    qs = qs.extra(select={'thread_count': 'SELECT COUNT(*) FROM forums_thread '
                                          'WHERE forums_thread.forum_id = '
                                          'forums_forum.id'})
    forums_ = [f for f in qs if f.allows_viewing_by(request.user)]
    return jingo.render(request, 'forums/forums.html',
                       {'forums': paginate(request, forums_)})
Пример #38
0
def list_documents_for_review(request, tag=None):
    """Lists wiki documents with revisions flagged for review"""
    tag_obj = tag and get_object_or_404(ReviewTag, name=tag) or None
    docs = paginate(request, Document.objects.filter_for_review(tag=tag_obj),
                    per_page=DOCUMENTS_PER_PAGE)
    return jingo.render(request, 'wiki/list_documents_for_review.html',
                        {'documents': docs,
                         'tag': tag_obj,
                         'tag_name': tag})
Пример #39
0
def revisions(request):
    """Dashboard for reviewing revisions"""

    filter_form = RevisionDashboardForm(request.GET)
    page = request.GET.get('page', 1)

    revisions = (Revision.objects.select_related('creator').order_by(
        '-created').defer('content'))

    query_kwargs = False

    # We can validate right away because no field is required
    if filter_form.is_valid():
        query_kwargs = {}
        query_kwargs_map = {
            'user': '******',
            'locale': 'document__locale',
            'topic': 'slug__icontains',
        }

        # Build up a dict of the filter conditions, if any, then apply
        # them all in one go.
        for fieldname, kwarg in query_kwargs_map.items():
            filter_arg = filter_form.cleaned_data[fieldname]
            if filter_arg:
                query_kwargs[kwarg] = filter_arg

        start_date = filter_form.cleaned_data['start_date']
        if start_date:
            end_date = (filter_form.cleaned_data['end_date']
                        or datetime.datetime.now())
            query_kwargs['created__range'] = [start_date, end_date]

    if query_kwargs:
        revisions = revisions.filter(**query_kwargs)
        total = revisions.count()
    else:
        # If no filters, just do a straight count(). It's the same
        # result, but much faster to compute.
        total = Revision.objects.count()

    # Only bother with this if we're actually going to get
    # some revisions from it. Otherwise it's a pointless but
    # potentially complex query.
    revisions = paginate(request, revisions, per_page=PAGE_SIZE)

    context = {'revisions': revisions, 'page': page, 'total': total}

    # Serve the response HTML conditionally upon reques type
    if request.is_ajax():
        return render(request,
                      'dashboards/includes/revision_dashboard_body.html',
                      context)
    else:
        context['form'] = filter_form

    return render(request, 'dashboards/revisions.html', context)
Пример #40
0
def review(request):
    """Review dashboard for a user, forum threads, announcements, etc."""
    threads = Thread.objects.filter(post__author=request.user).distinct()
    count = threads.count()
    threads = threads.select_related("creator", "last_post", "last_post__author")
    threads = paginate(request, threads, per_page=forum_constants.THREADS_PER_PAGE, count=count)

    return jingo.render(
        request, "dashboards/review.html", {"threads": threads, "announcements": Announcement.get_site_wide()}
    )
Пример #41
0
def questions(request):
    """View the questions."""

    filter = request.GET.get('filter')
    tagged = request.GET.get('tagged')
    tags = None
    sort_ = request.GET.get('sort')

    if sort_ == 'requested':
        order = '-num_votes_past_week'
    else:
        sort_ = None
        order = '-updated'

    question_qs = Question.objects.filter(creator__is_active=1,
                                          status=CONFIRMED)
    if filter == 'no-replies':
        question_qs = question_qs.filter(num_answers=0)
    elif filter == 'replies':
        question_qs = question_qs.filter(num_answers__gt=0)
    elif filter == 'solved':
        question_qs = question_qs.exclude(solution=None)
    elif filter == 'unsolved':
        question_qs = question_qs.filter(solution=None)
    elif filter == 'my-contributions' and request.user.is_authenticated():
        criteria = Q(answers__creator=request.user) | Q(creator=request.user)
        question_qs = question_qs.filter(criteria).distinct()
    else:
        filter = None

    feed_urls = ((reverse('questions.feed'),
                  QuestionsFeed().title()),)

    if tagged:
        tag_slugs = tagged.split(',')
        tags = Tag.objects.filter(slug__in=tag_slugs)
        if tags:
            for t in tags:
                question_qs = question_qs.filter(tags__in=[t.name])
            if len(tags) == 1:
                feed_urls += ((reverse('questions.tagged_feed',
                                       args=[tags[0].slug]),
                               TaggedQuestionsFeed().title(tags[0])),)
        else:
            question_qs = Question.objects.get_empty_query_set()

    question_qs = question_qs.order_by(order)
    questions_ = paginate(request, question_qs,
                          per_page=constants.QUESTIONS_PER_PAGE)

    return jingo.render(request, 'questions/questions.html',
                        {'questions': questions_, 'feeds': feed_urls,
                         'filter': filter, 'sort': sort_,
                         'top_contributors': _get_top_contributors(),
                         'tags': tags, 'tagged': tagged})
Пример #42
0
def revisions(request):
    """Dashboard for reviewing revisions"""

    filter_form = RevisionDashboardForm(request.GET)
    page = request.GET.get("page", 1)

    revisions = Revision.objects.select_related("creator").order_by("-created").defer("content")

    query_kwargs = False

    # We can validate right away because no field is required
    if filter_form.is_valid():
        query_kwargs = {}
        query_kwargs_map = {
            "user": "******",
            "locale": "document__locale",
            "topic": "slug__icontains",
        }

        # Build up a dict of the filter conditions, if any, then apply
        # them all in one go.
        for fieldname, kwarg in query_kwargs_map.items():
            filter_arg = filter_form.cleaned_data[fieldname]
            if filter_arg:
                query_kwargs[kwarg] = filter_arg

        start_date = filter_form.cleaned_data["start_date"]
        if start_date:
            end_date = filter_form.cleaned_data["end_date"] or datetime.datetime.now()
            query_kwargs["created__range"] = [start_date, end_date]

    if query_kwargs:
        revisions = revisions.filter(**query_kwargs)
        total = revisions.count()
    else:
        # If no filters, just do a straight count(). It's the same
        # result, but much faster to compute.
        total = Revision.objects.count()

    # Only bother with this if we're actually going to get
    # some revisions from it. Otherwise it's a pointless but
    # potentially complex query.
    revisions = paginate(request, revisions, per_page=PAGE_SIZE)

    context = {"revisions": revisions, "page": page, "total": total}

    # Serve the response HTML conditionally upon reques type
    if request.is_ajax():
        template = "dashboards/includes/revision_dashboard_body.html"
    else:
        template = "dashboards/revisions.html"
        context["form"] = filter_form

    return render(request, template, context)
Пример #43
0
def list_documents_for_review(request, tag=None):
    """Lists wiki documents with revisions flagged for review"""
    tag_obj = tag and get_object_or_404(ReviewTag, name=tag) or None
    docs = paginate(request,
                    Document.objects.filter_for_review(tag=tag_obj),
                    per_page=DOCUMENTS_PER_PAGE)
    return jingo.render(request, 'wiki/list_documents_for_review.html', {
        'documents': docs,
        'tag': tag_obj,
        'tag_name': tag
    })
Пример #44
0
def inbox(request, template):
    user = request.user
    messages = InboxMessage.uncached.filter(to=user).order_by('-created')
    count = messages.count()

    messages = paginate(request,
                        messages,
                        per_page=MESSAGES_PER_PAGE,
                        count=count)

    return render(request, template, {'msgs': messages})
Пример #45
0
def review(request):
    """Review dashboard for a user, forum threads, announcements, etc."""
    threads = Thread.objects.filter(post__author=request.user).distinct()
    count = threads.count()
    threads = threads.select_related('creator', 'last_post',
                                     'last_post__author')
    threads = paginate(request, threads,
                       per_page=forum_constants.THREADS_PER_PAGE, count=count)

    return render(request, 'dashboards/review.html', {
        'threads': threads,
        'announcements': Announcement.get_site_wide()})
Пример #46
0
def outbox(request, template):
    user = request.user
    messages = OutboxMessage.uncached.filter(sender=user).order_by('-created')
    count = messages.count()

    messages = paginate(request,
                        messages,
                        per_page=MESSAGES_PER_PAGE,
                        count=count)

    for msg in messages.object_list:
        _add_recipients(msg)

    return render(request, template, {'msgs': messages})
Пример #47
0
def review(request):
    """Review dashboard for a user, forum threads, announcements, etc."""
    threads = Thread.objects.filter(post__author=request.user).distinct()
    count = threads.count()
    threads = threads.select_related('creator', 'last_post',
                                     'last_post__author')
    threads = paginate(request,
                       threads,
                       per_page=forum_constants.THREADS_PER_PAGE,
                       count=count)

    return jingo.render(request, 'dashboards/review.html', {
        'threads': threads,
        'announcements': Announcement.get_site_wide()
    })
Пример #48
0
def posts(request, forum_slug, thread_id, form=None, post_preview=None,
          is_reply=False):
    """View all the posts in a thread."""
    thread = get_object_or_404(Thread, pk=thread_id)
    forum = thread.forum

    if forum.slug != forum_slug and not is_reply:
        new_forum = get_object_or_404(Forum, slug=forum_slug)
        if new_forum.allows_viewing_by(request.user):
            return HttpResponseRedirect(thread.get_absolute_url())
        raise Http404  # User has no right to view destination forum.
    elif forum.slug != forum_slug:
        raise Http404

    if not forum.allows_viewing_by(request.user):
        raise Http404

    posts_ = thread.post_set.all()
    count = posts_.count()
    if count:
        last_post = posts_[count - 1]
    else:
        last_post = None
    posts_ = posts_.select_related('author', 'updated_by')
    posts_ = posts_.extra(
        select={'author_post_count': 'SELECT COUNT(*) FROM forums_post WHERE '
                                     'forums_post.author_id = auth_user.id'})
    posts_ = paginate(request, posts_, constants.POSTS_PER_PAGE, count=count)

    if not form:
        form = ReplyForm()

    feed_urls = ((reverse('forums.posts.feed',
                          kwargs={'forum_slug': forum_slug,
                                  'thread_id': thread_id}),
                  PostsFeed().title(thread)),)

    is_watching_thread = (request.user.is_authenticated() and
                          NewPostEvent.is_notifying(request.user, thread))
    return jingo.render(request, 'forums/posts.html',
                        {'forum': forum, 'thread': thread,
                         'posts': posts_, 'form': form,
                         'count': count,
                         'last_post': last_post,
                         'post_preview': post_preview,
                         'is_watching_thread': is_watching_thread,
                         'feeds': feed_urls,
                         'forums': Forum.objects.all()})
Пример #49
0
def search(request, media_type):
    """Search the media gallery."""

    term = request.GET.get("q")
    if not term:
        url = reverse("gallery.gallery", args=[media_type])
        return HttpResponseRedirect(url)

    filter = Q(title__icontains=term) | Q(description__icontains=term)

    if media_type == "image":
        media_qs = Image.objects.filter(filter, locale=request.locale)
    elif media_type == "video":
        media_qs = Video.objects.filter(filter, locale=request.locale)
    else:
        raise Http404

    media = paginate(request, media_qs, per_page=ITEMS_PER_PAGE)

    return jingo.render(request, "gallery/search.html", {"media": media, "media_type": media_type, "q": term})
Пример #50
0
def list_documents(request, category=None, tag=None):
    """List wiki documents."""
    if category:
        try:
            category_id = int(category)
        except ValueError:
            raise Http404
        try:
            category = unicode(dict(CATEGORIES)[category_id])
        except KeyError:
            raise Http404

    tag_obj = tag and get_object_or_404(Tag, slug=tag) or None
    docs = Document.objects.filter_for_list(locale=request.locale,
                                             category=category,
                                             tag=tag_obj)
    docs = paginate(request, docs, per_page=DOCUMENTS_PER_PAGE)
    return jingo.render(request, 'wiki/list_documents.html',
                        {'documents': docs,
                         'category': category,
                         'tag': tag})
Пример #51
0
def list_documents(request, category=None, tag=None):
    """List wiki documents."""
    if category:
        try:
            category_id = int(category)
        except ValueError:
            raise Http404
        try:
            category = unicode(dict(CATEGORIES)[category_id])
        except KeyError:
            raise Http404

    tag_obj = tag and get_object_or_404(Tag, slug=tag) or None
    docs = Document.objects.filter_for_list(locale=request.locale,
                                            category=category,
                                            tag=tag_obj)
    docs = paginate(request, docs, per_page=DOCUMENTS_PER_PAGE)
    return jingo.render(request, 'wiki/list_documents.html', {
        'documents': docs,
        'category': category,
        'tag': tag
    })
Пример #52
0
def search(request, media_type):
    """Search the media gallery."""

    term = request.GET.get('q')
    if not term:
        url = reverse('gallery.gallery', args=[media_type])
        return HttpResponseRedirect(url)

    filter = Q(title__icontains=term) | Q(description__icontains=term)

    if media_type == 'image':
        media_qs = Image.objects.filter(filter, locale=request.locale)
    elif media_type == 'video':
        media_qs = Video.objects.filter(filter, locale=request.locale)
    else:
        raise Http404

    media = paginate(request, media_qs, per_page=ITEMS_PER_PAGE)

    return jingo.render(request, 'gallery/search.html',
                        {'media': media,
                         'media_type': media_type,
                         'q': term})
Пример #53
0
def recent_revisions(request):
    # Make writable
    request.GET = request.GET.copy()

    fragment = request.GET.pop('fragment', None)
    form = RevisionFilterForm(request.GET)
    revs = Revision.objects.order_by('-created')

    # We are going to ignore validation errors for the most part, but
    # this is needed to call the functions that generate `cleaned_data`
    # This helps in particular when bad user names are typed in.
    form.is_valid()

    # If something has gone very wrong, `cleaned_data` won't be there.
    if hasattr(form, 'cleaned_data'):
        if form.cleaned_data.get('locale'):
            revs = revs.filter(document__locale=form.cleaned_data['locale'])
        if form.cleaned_data.get('users'):
            revs = revs.filter(creator__in=form.cleaned_data['users'])
        if form.cleaned_data.get('start'):
            revs = revs.filter(created__gte=form.cleaned_data['start'])
        if form.cleaned_data.get('end'):
            revs = revs.filter(created__lte=form.cleaned_data['end'])

    revs = paginate(request, revs)

    c = {
        'revisions': revs,
        'form': form,
    }
    if fragment:
        template = 'wiki/includes/recent_revisions_fragment.html'
    else:
        template = 'wiki/recent_revisions.html'

    return render(request, template, c)
Пример #54
0
def list_documents(request, category=None, tag=None):
    """List wiki documents."""
    docs = Document.objects.filter(locale=request.locale).order_by('title')
    if category:
        docs = docs.filter(category=category)
        try:
            category_id = int(category)
        except ValueError:
            raise Http404
        try:
            category = unicode(dict(CATEGORIES)[category_id])
        except KeyError:
            raise Http404

    if tag:
        tagobj = get_object_or_404(Tag, slug=tag)
        docs = docs.filter(tags__name__in=[tagobj.name])

    docs = paginate(request, docs, per_page=DOCUMENTS_PER_PAGE)
    return jingo.render(request, 'wiki/list_documents.html', {
        'documents': docs,
        'category': category,
        'tag': tag
    })
Пример #55
0
def list_files(request):
    """Returns listing of all files"""
    files = paginate(request,
                     Attachment.objects.order_by('title'),
                     per_page=DOCUMENTS_PER_PAGE)
    return render(request, 'attachments/list_files.html', {'files': files})
Пример #56
0
def model_actions(model_class, request):
    """Returns paginated actions for the given model."""
    ct = ContentType.objects.get_for_model(model_class)
    actions = request.user.action_inbox.filter(content_type=ct)
    return paginate(request, actions, per_page=ACTIONS_PER_PAGE)
Пример #57
0
def search(request, template=None):
    """ES-specific search view"""

    # JSON-specific variables
    is_json = (request.GET.get('format') == 'json')
    callback = request.GET.get('callback', '').strip()
    mimetype = 'application/x-javascript' if callback else 'application/json'

    # Search "Expires" header format
    expires_fmt = '%A, %d %B %Y %H:%M:%S GMT'

    # Check callback is valid
    if is_json and callback and not jsonp_is_valid(callback):
        return HttpResponse(
            json.dumps({'error': _('Invalid callback function.')}),
            mimetype=mimetype, status=400)

    language = locale_or_default(
        request.GET.get('language', request.LANGUAGE_CODE))
    r = request.GET.copy()
    a = request.GET.get('a', '0')

    # Search default values
    try:
        category = (map(int, r.getlist('category')) or
                    settings.SEARCH_DEFAULT_CATEGORIES)
    except ValueError:
        category = settings.SEARCH_DEFAULT_CATEGORIES
    r.setlist('category', category)

    # Basic form
    if a == '0':
        r['w'] = r.get('w', constants.WHERE_BASIC)
    # Advanced form
    if a == '2':
        r['language'] = language
        r['a'] = '1'

    # TODO: Rewrite so SearchForm is unbound initially and we can use
    # `initial` on the form fields.
    if 'include_archived' not in r:
        r['include_archived'] = False

    search_form = SearchForm(r)

    if not search_form.is_valid() or a == '2':
        if is_json:
            return HttpResponse(
                json.dumps({'error': _('Invalid search data.')}),
                mimetype=mimetype,
                status=400)

        t = template if request.MOBILE else 'search/form.html'
        search_ = render(request, t, {
            'advanced': a, 'request': request,
            'search_form': search_form})
        search_['Cache-Control'] = 'max-age=%s' % \
                                   (settings.SEARCH_CACHE_PERIOD * 60)
        search_['Expires'] = (datetime.utcnow() +
                              timedelta(
                                minutes=settings.SEARCH_CACHE_PERIOD)) \
                              .strftime(expires_fmt)
        return search_

    cleaned = search_form.cleaned_data

    if request.MOBILE and cleaned['w'] == constants.WHERE_BASIC:
        cleaned['w'] = constants.WHERE_WIKI

    page = max(smart_int(request.GET.get('page')), 1)
    offset = (page - 1) * settings.SEARCH_RESULTS_PER_PAGE

    lang = language.lower()
    if settings.LANGUAGES.get(lang):
        lang_name = settings.LANGUAGES[lang]
    else:
        lang_name = ''

    # We use a regular S here because we want to search across
    # multiple doctypes.
    searcher = (UntypedS().es(urls=settings.ES_URLS)
                          .indexes(es_utils.READ_INDEX))

    wiki_f = F(model='wiki_document')
    question_f = F(model='questions_question')
    discussion_f = F(model='forums_thread')

    # Start - wiki filters

    if cleaned['w'] & constants.WHERE_WIKI:
        # Category filter
        if cleaned['category']:
            wiki_f &= F(document_category__in=cleaned['category'])

        # Locale filter
        wiki_f &= F(document_locale=language)

        # Product filter
        products = cleaned['product']
        for p in products:
            wiki_f &= F(product=p)

        # Topics filter
        topics = cleaned['topics']
        for t in topics:
            wiki_f &= F(topic=t)

        # Archived bit
        if a == '0' and not cleaned['include_archived']:
            # Default to NO for basic search:
            cleaned['include_archived'] = False
        if not cleaned['include_archived']:
            wiki_f &= F(document_is_archived=False)

    # End - wiki filters

    # Start - support questions filters

    if cleaned['w'] & constants.WHERE_SUPPORT:
        # Solved is set by default if using basic search
        if a == '0' and not cleaned['has_helpful']:
            cleaned['has_helpful'] = constants.TERNARY_YES

        # These filters are ternary, they can be either YES, NO, or OFF
        ternary_filters = ('is_locked', 'is_solved', 'has_answers',
                           'has_helpful')
        d = dict(('question_%s' % filter_name,
                  _ternary_filter(cleaned[filter_name]))
                 for filter_name in ternary_filters if cleaned[filter_name])
        if d:
            question_f &= F(**d)

        if cleaned['asked_by']:
            question_f &= F(question_creator=cleaned['asked_by'])

        if cleaned['answered_by']:
            question_f &= F(question_answer_creator=cleaned['answered_by'])

        q_tags = [t.strip() for t in cleaned['q_tags'].split(',')]
        for t in q_tags:
            if t:
                question_f &= F(question_tag=t)

        # Product filter
        products = cleaned['product']
        for p in products:
            question_f &= F(product=p)

        # Topics filter
        topics = cleaned['topics']
        for t in topics:
            question_f &= F(topic=t)

    # End - support questions filters

    # Start - discussion forum filters

    if cleaned['w'] & constants.WHERE_DISCUSSION:
        if cleaned['author']:
            discussion_f &= F(post_author_ord=cleaned['author'])

        if cleaned['thread_type']:
            if constants.DISCUSSION_STICKY in cleaned['thread_type']:
                discussion_f &= F(post_is_sticky=1)

            if constants.DISCUSSION_LOCKED in cleaned['thread_type']:
                discussion_f &= F(post_is_locked=1)

        if cleaned['forum']:
            discussion_f &= F(post_forum_id__in=cleaned['forum'])

    # End - discussion forum filters

    # Created filter
    unix_now = int(time.time())
    interval_filters = (
        ('created', cleaned['created'], cleaned['created_date']),
        ('updated', cleaned['updated'], cleaned['updated_date']))
    for filter_name, filter_option, filter_date in interval_filters:
        if filter_option == constants.INTERVAL_BEFORE:
            before = {filter_name + '__gte': 0,
                      filter_name + '__lte': max(filter_date, 0)}

            discussion_f &= F(**before)
            question_f &= F(**before)
        elif filter_option == constants.INTERVAL_AFTER:
            after = {filter_name + '__gte': min(filter_date, unix_now),
                     filter_name + '__lte': unix_now}

            discussion_f &= F(**after)
            question_f &= F(**after)

    # In basic search, we limit questions from the last
    # SEARCH_DEFAULT_MAX_QUESTION_AGE seconds.
    if a == '0':
        start_date = unix_now - settings.SEARCH_DEFAULT_MAX_QUESTION_AGE
        question_f &= F(created__gte=start_date)

    # Note: num_voted (with a d) is a different field than num_votes
    # (with an s). The former is a dropdown and the latter is an
    # integer value.
    if cleaned['num_voted'] == constants.INTERVAL_BEFORE:
        question_f &= F(question_num_votes__lte=max(cleaned['num_votes'], 0))
    elif cleaned['num_voted'] == constants.INTERVAL_AFTER:
        question_f &= F(question_num_votes__gte=cleaned['num_votes'])

    # Done with all the filtery stuff--time  to generate results

    # Combine all the filters and add to the searcher
    doctypes = []
    final_filter = F()
    if cleaned['w'] & constants.WHERE_WIKI:
        doctypes.append(DocumentMappingType.get_mapping_type_name())
        final_filter |= wiki_f

    if cleaned['w'] & constants.WHERE_SUPPORT:
        doctypes.append(QuestionMappingType.get_mapping_type_name())
        final_filter |= question_f

    if cleaned['w'] & constants.WHERE_DISCUSSION:
        doctypes.append(ThreadMappingType.get_mapping_type_name())
        final_filter |= discussion_f

    searcher = searcher.doctypes(*doctypes)
    searcher = searcher.filter(final_filter)

    if 'explain' in request.GET and request.GET['explain'] == '1':
        searcher = searcher.explain()

    documents = ComposedList()

    try:
        cleaned_q = cleaned['q']

        # Set up the highlights
        # First 500 characters of content in one big fragment
        searcher = searcher.highlight(
            'question_content', 'discussion_content', 'document_summary',
            pre_tags=['<b>'],
            post_tags=['</b>'],
            number_of_fragments=0,
            fragment_size=500)

        # Set up boosts
        searcher = searcher.boost(
            question_title=4.0,
            question_content=3.0,
            question_answer_content=3.0,
            post_title=2.0,
            post_content=1.0,
            document_title=6.0,
            document_content=1.0,
            document_keywords=8.0,
            document_summary=2.0,

            # Text phrases in document titles and content get an extra
            # boost.
            document_title__text_phrase=10.0,
            document_content__text_phrase=8.0)

        # Apply sortby for advanced search of questions
        if cleaned['w'] == constants.WHERE_SUPPORT:
            sortby = cleaned['sortby']
            try:
                searcher = searcher.order_by(
                    *constants.SORT_QUESTIONS[sortby])
            except IndexError:
                # Skip index errors because they imply the user is
                # sending us sortby values that aren't valid.
                pass

        # Apply sortby for advanced search of kb documents
        if cleaned['w'] == constants.WHERE_WIKI:
            sortby = cleaned['sortby_documents']
            try:
                searcher = searcher.order_by(
                    *constants.SORT_DOCUMENTS[sortby])
            except IndexError:
                # Skip index errors because they imply the user is
                # sending us sortby values that aren't valid.
                pass

        # Build the query
        if cleaned_q:
            query_fields = chain(*[cls.get_query_fields()
                                   for cls in get_mapping_types()])

            query = {}
            # Create text and text_phrase queries for every field
            # we want to search.
            for field in query_fields:
                for query_type in ['text', 'text_phrase']:
                    query['%s__%s' % (field, query_type)] = cleaned_q

            searcher = searcher.query(should=True, **query)

        num_results = min(searcher.count(), settings.SEARCH_MAX_RESULTS)

        # TODO - Can ditch the ComposedList here, but we need
        # something that paginate can use to figure out the paging.
        documents = ComposedList()
        documents.set_count(('results', searcher), num_results)

        results_per_page = settings.SEARCH_RESULTS_PER_PAGE
        pages = paginate(request, documents, results_per_page)

        # Facets
        product_facets = {}

        # If we know there aren't any results, let's cheat and in
        # doing that, not hit ES again.
        if num_results == 0:
            searcher = []
        else:
            # Get the documents we want to show and add them to
            # docs_for_page
            documents = documents[offset:offset + results_per_page]

            if len(documents) == 0:
                # If the user requested a page that's beyond the
                # pagination, then documents is an empty list and
                # there are no results to show.
                searcher = []
            else:
                bounds = documents[0][1]
                searcher = searcher.values_dict()[bounds[0]:bounds[1]]

                # If we are doing basic search, we show product facets.
                if a == '0':
                    pfc = searcher.facet(
                        'product', filtered=True).facet_counts()
                    product_facets = dict(
                        [(p['term'], p['count']) for p in pfc['product']])

        results = []
        for i, doc in enumerate(searcher):
            rank = i + offset

            if doc['model'] == 'wiki_document':
                summary = _build_es_excerpt(doc)
                if not summary:
                    summary = doc['document_summary']
                result = {
                    'title': doc['document_title'],
                    'type': 'document'}

            elif doc['model'] == 'questions_question':
                summary = _build_es_excerpt(doc)
                if not summary:
                    # We're excerpting only question_content, so if
                    # the query matched question_title or
                    # question_answer_content, then there won't be any
                    # question_content excerpts. In that case, just
                    # show the question--but only the first 500
                    # characters.
                    summary = bleach.clean(
                        doc['question_content'], strip=True)[:500]

                result = {
                    'title': doc['question_title'],
                    'type': 'question',
                    'is_solved': doc['question_is_solved'],
                    'num_answers': doc['question_num_answers'],
                    'num_votes': doc['question_num_votes'],
                    'num_votes_past_week': doc['question_num_votes_past_week']}

            else:
                summary = _build_es_excerpt(doc)
                result = {
                    'title': doc['post_title'],
                    'type': 'thread'}

            result['url'] = doc['url']
            result['object'] = ObjectDict(doc)
            result['search_summary'] = summary
            result['rank'] = rank
            result['score'] = doc._score
            result['explanation'] = escape(format_explanation(
                    doc._explanation))
            results.append(result)

    except ES_EXCEPTIONS as exc:
        # Handle timeout and all those other transient errors with a
        # "Search Unavailable" rather than a Django error page.
        if is_json:
            return HttpResponse(json.dumps({'error':
                                             _('Search Unavailable')}),
                                mimetype=mimetype, status=503)

        # Cheating here: Convert from 'Timeout()' to 'timeout' so
        # we have less code, but still have good stats.
        exc_bucket = repr(exc).lower().strip('()')
        statsd.incr('search.esunified.{0}'.format(exc_bucket))

        import logging
        logging.exception(exc)

        t = 'search/mobile/down.html' if request.MOBILE else 'search/down.html'
        return render(request, t, {'q': cleaned['q']}, status=503)

    items = [(k, v) for k in search_form.fields for
             v in r.getlist(k) if v and k != 'a']
    items.append(('a', '2'))

    if is_json:
        # Models are not json serializable.
        for r in results:
            del r['object']
        data = {}
        data['results'] = results
        data['total'] = len(results)
        data['query'] = cleaned['q']
        if not results:
            data['message'] = _('No pages matched the search criteria')
        json_data = json.dumps(data)
        if callback:
            json_data = callback + '(' + json_data + ');'

        return HttpResponse(json_data, mimetype=mimetype)

    fallback_results = None
    if num_results == 0:
        fallback_results = _fallback_results(language, cleaned['product'])

    results_ = render(request, template, {
        'num_results': num_results,
        'results': results,
        'fallback_results': fallback_results,
        'q': cleaned['q'],
        'w': cleaned['w'],
        'product': cleaned['product'],
        'products': Product.objects.filter(visible=True),
        'product_facets': product_facets,
        'pages': pages,
        'search_form': search_form,
        'lang_name': lang_name, })
    results_['Cache-Control'] = 'max-age=%s' % \
                                (settings.SEARCH_CACHE_PERIOD * 60)
    results_['Expires'] = (datetime.utcnow() +
                           timedelta(minutes=settings.SEARCH_CACHE_PERIOD)) \
                           .strftime(expires_fmt)
    results_.set_cookie(settings.LAST_SEARCH_COOKIE, urlquote(cleaned['q']),
                        max_age=3600, secure=False, httponly=False)

    return results_