def archive_year(request, year, template_name="blog/archive_year.html", extra_context=None): """ Year archive page view, list all article published the given year. :param request: The incoming request. :param year: The desired archive's year. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Year/month cleaning year = int(year) if year == 0: raise Http404() # Retrieve all published articles for the given year published_articles = ( Article.objects.published() .filter(pub_date__year=year) .select_related("author") .prefetch_related("tags", "categories") ) # Articles list pagination paginator, page = paginate(published_articles, request, NB_ARTICLES_PER_PAGE) # Render the template context = {"title": _("Articles for year %d") % year, "year": year} update_context_for_pagination(context, "articles", request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def image_attachment_list(request, template_name='imageattachments/image_attachment_list.html', extra_context=None): """ List all recently published image attachments. :param request: The incoming request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Retrieve all published image attachments published_images = ImageAttachment.objects.published_public().select_related('license') # Images list pagination paginator, page = paginate(published_images, request, NB_IMG_ATTACHMENTS_PER_PAGE) # Render the template context = { 'title': _('Image attachments'), } update_context_for_pagination(context, 'images', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def category_detail(request, hierarchy, template_name="blog/category_detail.html", extra_context=None): """ Detail view for a specific category. :param hierarchy: The desired category's slug(s) hierarchy. :param request: The incoming request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Get the desired category manager = ArticleCategory.objects.select_related("parent") category_obj = get_object_or_404(manager, slug_hierarchy=hierarchy) # Related articles list pagination paginator, page = paginate( category_obj.articles.published().select_related("author").prefetch_related("tags", "categories"), request, NB_ARTICLES_PER_PAGE, ) # Render the template context = {"title": _("Category %s") % category_obj.name, "category": category_obj} update_context_for_pagination(context, "related_articles", request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def license_detail(request, slug, template_name="blog/license_detail.html", extra_context=None): """ Detail view for a specific license. :param slug: The desired license's slug. :param request: The incoming request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Get the desired license license_obj = get_object_or_404(License, slug=slug) # Related articles list pagination paginator, page = paginate( license_obj.articles.published().select_related("author").prefetch_related("tags", "categories"), request, NB_ARTICLES_PER_PAGE, ) # Render the template context = {"title": _("License %s") % license_obj.name, "license": license_obj} update_context_for_pagination(context, "related_articles", request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def accounts_list(request, template_name='accounts/accounts_list.html', extra_context=None): """ Accounts page view, display all registered user accounts as a paginated list. :param request: The current request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Accounts listing user_account_list = UserProfile.objects.get_active_users_accounts().select_related('user') # Accounts list pagination paginator, page = paginate(user_account_list, request, NB_ACCOUNTS_PER_PAGE) # Render the template context = { 'title': _('Members list'), } update_context_for_pagination(context, 'accounts', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def snippet_list(request, template_name='snippets/snippet_list.html', extra_context=None): """ Code snippets list view. :param request: The incoming request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Retrieve all published code snippets published_snippets = CodeSnippet.objects.public_snippets().select_related('author') # Code snippets list pagination paginator, page = paginate(published_snippets, request, NB_SNIPPETS_PER_PAGE) # Render the template context = { 'title': _('Code snippets list'), } update_context_for_pagination(context, 'snippets', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def my_posts_list(request, template_name='forum/forum_myposts_list.html', extra_context=None): """ Current user's posts list. :param request: The current request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Get the post list for the current user post_list = request.user.forum_posts.published() \ .select_related('author__user_profile', 'last_modification_by').prefetch_related('attachments') # Post list pagination paginator, page = paginate(post_list, request, NB_FORUM_POST_PER_PAGE) # Render the template context = { 'title': _('My forum posts list'), } update_context_for_pagination(context, 'posts', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def my_forums_subscription_list(request, template_name='forum/forum_myforumssubscription_list.html', extra_context=None): """ Current user's forums subscription list. :param request: The current request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Get all subscriptions subscriptions = ForumSubscription.objects.filter(user=request.user, active=True).select_related('forum') # Forum subscriptions list pagination paginator, page = paginate(subscriptions, request, NB_FORUM_THREAD_PER_PAGE) # Render the template context = { 'title': _('My forum subscriptions list'), } update_context_for_pagination(context, 'forum_subscriptions', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def msg_trashbox(request, template_name='privatemsg/trashbox.html', extra_context=None): """ Display the trashbox for the current user. :param request: The current request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Get the messages list for the current user messages = PrivateMessage.objects.trash_for(request.user).select_related('parent_msg', 'sender', 'recipient') # Messages list pagination paginator, page = paginate(messages, request, NB_PRIVATE_MSG_PER_PAGE) # Render the template context = { 'title': _('Private messages trash'), 'deletion_timeout_days': DELETED_MSG_DELETION_TIMEOUT_DAYS } update_context_for_pagination(context, 'private_messages', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def my_threads_list(request, template_name='forum/forum_mythreads_list.html', extra_context=None): """ Current user's threads list. :param request: The current request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Get the thread list for the current user thread_list = ForumThread.objects.published().filter(first_post__author=request.user) \ .select_related('first_post__author', 'last_post__author') # Thread list pagination paginator, page = paginate(thread_list, request, NB_FORUM_THREAD_PER_PAGE) # Render the template context = { 'title': _('My forum threads list'), } update_context_for_pagination(context, 'threads', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def msg_inbox(request, filterby='all', template_name='privatemsg/inbox.html', extra_context=None): """ Display the inbox for the current user. :param request: The current request. :param filterby: The selected filtering option. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Get the messages list for the current user messages = PrivateMessage.objects.inbox_for(request.user).select_related('parent_msg', 'sender') # Filter the list if filterby == 'read': messages = messages.filter(read_at__isnull=False) elif filterby == 'unread': messages = messages.filter(read_at__isnull=True) # Messages list pagination paginator, page = paginate(messages, request, NB_PRIVATE_MSG_PER_PAGE) # Render the template context = { 'title': _('Private messages inbox'), 'filter_by': filterby } update_context_for_pagination(context, 'private_messages', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def my_threads_subscription_list(request, template_name='forum/forum_mythreadssubscription_list.html', extra_context=None): """ Current user's threads subscription list. :param request: The current request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Get all subscriptions subscriptions = ForumThreadSubscription.objects.filter(user=request.user, thread__deleted_at__isnull=True, active=True) \ .select_related('thread__first_post__author', 'thread__last_post__author') # Thread subscriptions list pagination paginator, page = paginate(subscriptions, request, NB_FORUM_THREAD_PER_PAGE) # Render the template context = { 'title': _('My forum thread subscriptions list'), } update_context_for_pagination(context, 'thread_subscriptions', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def my_ticket_subscription_list(request, template_name='bugtracker/issueticket_mysubscriptionslist.html', extra_context=None): """ List of all issue tickets subscribed by the user, paginated view. Can be sorted using the publication date or modification date with ``?sortby=pubdate`` or ``?sortby=moddate``. Can change sort orientation with ``?sortfrom=recent`` (recent to old) or ``?sortfrom=old`` (old to recent). Can filter status, priority and difficulty using ``?status=XXX``, ``?priority=XXX`` or/and ``?difficulty=XXX`` :param request: The incoming request. :param template_name: The template to use for the view. :param extra_context: Any extra context dict. """ current_user = request.user issue_subscriptions = IssueTicketSubscription.objects.select_related('issue') \ .filter(user=current_user, active=True) # Issues list pagination paginator, page = paginate(issue_subscriptions, request, NB_ISSUES_PER_PAGE) # Template rendering context = { 'title': _('My tickets subscription list'), } update_context_for_pagination(context, 'subscriptions', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def license_list(request, template_name='licenses/license_list.html', extra_context=None): """ List view of all licenses. :param request: The incoming request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Retrieve all licenses queryset = License.objects.all() # Licenses list pagination paginator, page = paginate(queryset, request, NB_LICENSES_PER_PAGE) # Render the template context = { 'title': _('Licenses list'), } update_context_for_pagination(context, 'licenses', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def blocked_user_list(request, template_name='privatemsg/blocked_user_list.html', extra_context=None): """ Display all blocked user for the current user. :param request: The current request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Get all blocked user list for the current user blocked_user_list = BlockedUser.objects.blocked_users_for(request.user).select_related('blocked_user') # User list pagination paginator, page = paginate(blocked_user_list, request, NB_BLOCKED_USERS_PER_PAGE) # Render the template context = { 'title': _('Blocked users list'), } update_context_for_pagination(context, 'blocked_users', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def _generic_tickets_list(queryset, request, template_name, context): """ List of all issue tickets from the given queryset, paginated view. Can be sorted using the publication date or modification date with ``?sortby=pubdate`` or ``?sortby=moddate``. Can change sort orientation with ``?sortfrom=recent`` (recent to old) or ``?sortfrom=old`` (old to recent). Can filter status, priority and difficulty using ``?status=XXX``, ``?priority=XXX`` or/and ``?difficulty=XXX`` :param queryset: The queryset to source data from. :param request: The incoming request. :param template_name: The template to use for the view. :param context: Any extra context dict. """ # Issues sorting sort_by = request.GET.get('sortby', 'pubdate') sort_from = request.GET.get('sortfrom', 'recent') if sort_by == 'moddate': if sort_from == 'recent': order_by = '-last_modification_date' else: order_by = 'last_modification_date' else: if sort_from == 'recent': order_by = '-submission_date' else: order_by = 'submission_date' issues_list = queryset.order_by(order_by) # Issues filtering filter_status = request.GET.get('status', None) if filter_status: issues_list = issues_list.filter(status=filter_status) filter_priority = request.GET.get('priority', None) if filter_priority: issues_list = issues_list.filter(priority=filter_priority) filter_difficulty = request.GET.get('difficulty', None) if filter_difficulty: issues_list = issues_list.filter(status=filter_difficulty) # Issues list pagination paginator, page = paginate(issues_list.select_related('submitter'), request, NB_ISSUES_PER_PAGE) # Template rendering sort_context = { 'sort_sortby': sort_by, 'sort_sortfrom': sort_from, 'sort_status': filter_status, 'sort_priority': filter_priority, 'sort_difficulty': filter_difficulty, } context.update(sort_context) update_context_for_pagination(context, 'issues', request, paginator, page) return TemplateResponse(request, template_name, context)
def article_list(request, template_name="blog/article_list.html", extra_context=None): """ Blog home page view, list all recently published article. :param request: The incoming request. :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Retrieve all published articles published_articles = Article.objects.published().select_related("author").prefetch_related("tags", "categories") # Articles list pagination paginator, page = paginate(published_articles, request, NB_ARTICLES_PER_PAGE) # Render the template context = {"title": _("Articles")} update_context_for_pagination(context, "articles", request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def notification_list(request, filterby='all', template_name='notifications/notification_list.html', extra_context=None): """ Notifications list view, can display all notifications, unread ones or only read ones using ``filterby`` parameter (valid options: None, 'read' or 'unread'). :param request: The current request. :param filterby: The filtering option (None, read or unread) :param template_name: The template name to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ # Get the notifications list for the current user notifications = Notification.objects.filter(recipient=request.user) # Filter the list if filterby == 'read': notifications = notifications.filter(unread=False) elif filterby == 'unread': notifications = notifications.filter(unread=True) # Notifications list pagination paginator, page = paginate(notifications, request, NB_NOTIFICATIONS_PER_PAGE) # Render the template context = { 'title': _('Notifications list'), 'filter_by': filterby, 'deletion_timeout_days': READ_NOTIFICATION_DELETION_TIMEOUT_DAYS } update_context_for_pagination(context, 'notifications', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def forum_thread_show(request, pk, slug, template_name='forum/forum_thread_detail.html', mark_as_unread_post_action='mark_unread', extra_context=None): """ Detail view of the given forum's thread. :param request: The current request. :param pk: The forum's thread's PK. :param slug: The forum's thread's slug. :param template_name: The template name to be used. :param mark_as_unread_post_action: "mark as unread" POST submit name. :param extra_context: Any extra context for the template. :return: TemplateResponse """ assert slug is not None # Get the thread object by pk manager = ForumThread.objects.published().select_related('parent_forum', 'first_post__author') thread_obj = get_object_or_404(manager, pk=pk, slug=slug) # Handle private thread if not thread_obj.has_access(request.user): raise PermissionDenied() # Handle "mark as unread" action current_user = request.user if request.method == 'POST' and current_user.is_authenticated(): if request.POST.get(mark_as_unread_post_action, None): # Mark as unread ReadForumThreadTracker.objects.mark_thread_as_unread(current_user, thread_obj) # Redirect to the parent forum return HttpResponseRedirect(thread_obj.parent_forum.get_absolute_url()) # Paginate thread's posts paginator, page = paginate(thread_obj.posts.published().order_by('pub_date') .select_related('author__user_profile', 'last_modification_by') .prefetch_related('attachments'), request, NB_FORUM_POST_PER_PAGE) # Check if the current user has subscribed to the thread if current_user.is_authenticated(): has_subscribe_to_thread = ForumThreadSubscription.objects.has_subscribed_to_thread(current_user, thread_obj) # Also handle read marker ReadForumThreadTracker.objects.mark_thread_as_read(current_user, thread_obj) else: has_subscribe_to_thread = False # Render the template context = { 'title': _('Thread %s') % thread_obj.title, 'thread': thread_obj, 'forum': thread_obj.parent_forum, 'has_subscribe_to_thread': has_subscribe_to_thread, } update_context_for_pagination(context, 'posts', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)
def forum_show(request, hierarchy, template_name='forum/forum_detail.html', extra_context=None): """ Detail view for the specified forum or sub-forum. :param hierarchy: The desired forum's slug hierarchy. :param request: The current request. :param template_name: The template to be used. :param extra_context: Any extra context for the template. :return: TemplateResponse """ assert hierarchy is not None # Get the forum object forum_obj = get_object_or_404(Forum, slug_hierarchy=hierarchy) # Check authorization if forum is private if not forum_obj.has_access(request.user): raise PermissionDenied() # Get all threads in this forum queryset = ForumThread.objects.display_ordered(forum_obj) \ .select_related('first_post__author', 'last_post__author') # Prefetch posts and subscriptions current_user = request.user if current_user.is_authenticated(): prefetch_posts = Prefetch('posts', queryset=ForumThreadPost.objects.filter(author=current_user), to_attr='user_posts') prefetch_subscriptions = Prefetch('subscribers', queryset=ForumThreadSubscription.objects.filter(user=current_user), to_attr='user_subscriptions') queryset = queryset.prefetch_related(prefetch_posts, prefetch_subscriptions) # Related thread list pagination paginator, page = paginate(queryset, request, NB_FORUM_THREAD_PER_PAGE) # Prefetch child forums if not page.has_previous(): child_forums = forum_obj.children.all().order_by('ordering') else: # Avoid useless SQL request on other pages child_forums = None # Avoid useless SQL request for anonymous if current_user.is_authenticated(): has_subscribe_to_forum = ForumSubscription.objects.has_subscribed_to_forum(current_user, forum_obj) else: has_subscribe_to_forum = False # Render the template context = { 'title': _('Forum %s') % forum_obj.title, 'forum': forum_obj, 'child_forums': child_forums, 'has_subscribe_to_forum': has_subscribe_to_forum } update_context_for_pagination(context, 'threads', request, paginator, page) if extra_context is not None: context.update(extra_context) # Prefetch read markers if current_user.is_authenticated(): parent_forum_last_read_date = ReadForumTracker.objects.get_marker_for_forum(current_user, forum_obj) thread_markers = ReadForumThreadTracker.objects.get_marker_for_threads(current_user, page.object_list) context['read_markers'] = { 'parent_forum_last_read_date': parent_forum_last_read_date, 'thread_markers': thread_markers } return TemplateResponse(request, template_name, context)
def ticket_show(request, pk, template_name='bugtracker/issueticket_detail.html', issue_comment_form=IssueCommentCreationForm, extra_context=None): """ Detail view of the given ticket. comments can be reverse sorted (from new to old) using the GET parameter ``?sort=reverse``. :param pk: The ticket PK. :param template_name: The template to use for the view. :param issue_comment_form: The issue comment form to be used. :param request: The incoming request. :param extra_context: Any extra context dict. """ # Reverse comments sorting if request.GET.get('sort', None) == 'reverse': order_by = '-pub_date' cur_order_by = 'reverse' else: order_by = 'pub_date' cur_order_by = '' # Get the ticket and related comments manager = IssueTicket.objects.select_related('submitter', 'assigned_to', 'component') issue_obj = get_object_or_404(manager, pk=pk) issue_comments_list = issue_obj.comments.order_by(order_by) # Issue's comments pagination paginator, page = paginate(issue_comments_list .select_related('author') .prefetch_related('changes'), request, NB_ISSUE_COMMENTS_PER_PAGE) # Get the user preferences current_user = request.user if current_user.is_authenticated(): notify_of_reply = current_user.bugtracker_profile.notify_of_reply_by_default has_subscribe_to_issue = IssueTicketSubscription.objects.has_subscribed_to_issue(current_user, issue_obj) else: notify_of_reply = False has_subscribe_to_issue = False is_flooding = False # Handle POST requests if request.method == "POST": # Only authenticated user can post comment if not current_user.is_authenticated(): raise PermissionDenied() # Refresh anti flood only on POST is_flooding = current_user.bugtracker_profile.is_flooding() # Handle form (with anti flood) form = issue_comment_form(request.POST) if form.is_valid() and not is_flooding: opts = { 'request': request, 'issue': issue_obj, 'author': current_user, } new_obj = form.save(**opts) # Re-arm anti flood protection current_user.bugtracker_profile.rearm_flooding_delay_and_save() # Redirect to the newly created comment return HttpResponseRedirect(new_obj.get_absolute_url()) else: form = issue_comment_form(initial={'notify_of_reply': notify_of_reply}) # Render the template context = { 'cur_order_by': cur_order_by, 'is_flooding': is_flooding, 'flood_delay_sec': NB_SECONDS_BETWEEN_COMMENTS, 'issue': issue_obj, 'has_subscribe_to_issue': has_subscribe_to_issue, 'comment_form': form, 'title': _('Ticket detail'), } update_context_for_pagination(context, 'issue_comments', request, paginator, page) if extra_context is not None: context.update(extra_context) return TemplateResponse(request, template_name, context)