Пример #1
0
def searchtable(request):
    if request.method == 'GET':
        return HttpResponse('登录成功了,返回吧。这个页面还没做')
    # time.sleep(0.1)  # 测试前端用户感知,测试结束去掉
    json_data = request.body.decode('utf-8')
    info = json.loads(json_data)
    find_str = info.get('find_str', '')
    current_page = info.get('pn', 1)
    # table_names = TableData.objects.filter(table_name__contains=find_str).values('table_name')[:10]
    table_names = TableData.objects.filter(
        table_name__contains=find_str).values('table_name').order_by()
    paginator = Paginator(table_names, 10)  # Paginator生成一个对象,然后传入queryset,
    try:  # 以及每页显示的个数,这里每页显示十个
        page_obj = paginator.page(current_page)  # 根据get方法取到的数字显示页数
    except EmptyPage as e:  # 如果get方法获取了一个没有的页数则显示第一页
        page_obj = paginator.page(1)
    except PageNotAnInteger as e:  # 传入一个字符串也显示第一页
        page_obj = paginator.page(1)
    pagerange = paginator.get_elided_page_range(current_page,
                                                on_each_side=3,
                                                on_ends=2)
    page_obj.my_page_range = pagerange

    return render(request, 'mycharts/searchresult.html', {
        'tables': table_names,
        'page_obj': page_obj
    })
Пример #2
0
    def get(self, request):
        """lets see your cute faces"""
        filters = {}
        software = request.GET.get("software")
        if not software or software == "bookwyrm":
            filters["bookwyrm_user"] = True
        scope = request.GET.get("scope")
        if scope == "local":
            filters["local"] = True

        users = suggested_users.get_annotated_users(request.user, **filters)
        sort = request.GET.get("sort")
        if sort == "recent":
            users = users.order_by("-last_active_date")
        else:
            users = users.order_by("-mutuals", "-last_active_date")

        paginated = Paginator(users, 12)

        page = paginated.get_page(request.GET.get("page"))
        data = {
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
            "users":
            page,
        }
        return TemplateResponse(request, "directory/directory.html", data)
Пример #3
0
    def get(self, request):
        """view current reports"""
        filters = {}

        resolved = request.GET.get("resolved") == "true"
        server = request.GET.get("server")
        if server:
            filters["user__federated_server__server_name"] = server
        username = request.GET.get("username")
        if username:
            filters["user__username__icontains"] = username
        filters["resolved"] = resolved

        reports = models.Report.objects.filter(**filters)
        paginated = Paginator(reports, PAGE_LENGTH)
        page = paginated.get_page(request.GET.get("page"))
        data = {
            "resolved":
            resolved,
            "server":
            server,
            "reports":
            page,
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
        }
        return TemplateResponse(request, "settings/reports/reports.html", data)
Пример #4
0
def listing(request, page):
    keywords = Keyword.objects.all().order_by("name")
    paginator = Paginator(keywords, 2)
    page_object = paginator.get_page(page)
    page_object.adjusted_elided_pages = paginator.get_elided_page_range(page)
    context = {"page_obj": page_object}
    return render(request, "terms/keyword_list.html", context)
Пример #5
0
    def get(self, request, job_id):
        """status of an import job"""
        job = get_object_or_404(models.ImportJob, id=job_id)
        if job.user != request.user:
            raise PermissionDenied()

        items = job.items.order_by("index").filter(fail_reason__isnull=False,
                                                   book_guess__isnull=True)

        paginated = Paginator(items, PAGE_LENGTH)
        page = paginated.get_page(request.GET.get("page"))
        data = {
            "job":
            job,
            "items":
            page,
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
            "complete":
            True,
        }

        return TemplateResponse(request, "import/troubleshoot.html", data)
Пример #6
0
    def get(self, request, author_id):
        """landing page for an author"""
        author = get_object_or_404(models.Author, id=author_id)

        if is_api_request(request):
            return ActivitypubResponse(author.to_activity())

        default_editions = models.Edition.objects.filter(
            parent_work=OuterRef("parent_work")
        ).order_by("-edition_rank")

        books = (
            models.Edition.viewer_aware_objects(request.user)
            .filter(Q(authors=author) | Q(parent_work__authors=author))
            .annotate(default_id=Subquery(default_editions.values("id")[:1]))
            .filter(default_id=F("id"))
            .order_by("-first_published_date", "-published_date", "-created_date")
            .prefetch_related("authors")
        ).distinct()

        paginated = Paginator(books, PAGE_LENGTH)
        page = paginated.get_page(request.GET.get("page"))
        data = {
            "author": author,
            "books": page,
            "page_range": paginated.get_elided_page_range(
                page.number, on_each_side=2, on_ends=1
            ),
        }
        return TemplateResponse(request, "author/author.html", data)
Пример #7
0
def pendingDiagnosis(request):
    if request.method == 'POST':
        request.session['appointment_id'] = request.POST.get('appointment')
        return redirect('/doctor/pendingDiagnosis/call')
        # return redirect('/doctor/pendingDiagnosis/detail')
    identity_card_no = request.session['identity_card_no']
    doctor = models.Doctor.objects.get(identity_card_no=identity_card_no)
    appointment_records = models.Appointment.objects.filter(doctor=doctor,
                                                            isActive=True)
    appointment_records = appointment_records.order_by('-appointment_date',
                                                       '-appointment_time',
                                                       '-create_time')  # 排序
    num_per_page = 5
    paginator = Paginator(appointment_records, num_per_page)
    page = request.GET.get('page', 1)
    try:
        page_obj = paginator.page(page)
    except PageNotAnInteger:
        page_obj = paginator.page(1)
    except EmptyPage:
        page_obj = paginator.page(paginator.num_pages)
    is_paginated = True if paginator.num_pages > 1 else False
    page_range = paginator.get_elided_page_range(page,
                                                 on_each_side=3,
                                                 on_ends=2)

    return render(request, 'doctor/pending.html', locals())
Пример #8
0
    def get(self, request, book_id):
        """list of editions of a book"""
        work = get_object_or_404(models.Work, id=book_id)

        if is_api_request(request):
            return ActivitypubResponse(work.to_edition_list(**request.GET))
        filters = {}

        if request.GET.get("language"):
            filters["languages__contains"] = [request.GET.get("language")]
        if request.GET.get("format"):
            filters["physical_format__iexact"] = request.GET.get("format")

        editions = work.editions.order_by("-edition_rank")
        languages = set(sum(editions.values_list("languages", flat=True), []))

        editions = editions.filter(**filters)

        query = request.GET.get("q")
        if query:
            searchable_array_fields = ["languages", "publishers"]
            searchable_fields = [
                "title",
                "physical_format",
                "isbn_10",
                "isbn_13",
                "oclc_number",
                "asin",
            ]
            search_filter_entries = [{
                f"{f}__icontains": query
            } for f in searchable_fields] + [{
                f"{f}__iexact": query
            } for f in searchable_array_fields]
            editions = editions.filter(
                reduce(operator.or_, (Q(**f) for f in search_filter_entries)))

        paginated = Paginator(editions, PAGE_LENGTH)
        page = paginated.get_page(request.GET.get("page"))
        data = {
            "editions":
            page,
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
            "work":
            work,
            "work_form":
            forms.EditionFromWorkForm(instance=work),
            "languages":
            languages,
            "formats":
            set(e.physical_format.lower() for e in editions
                if e.physical_format),
        }
        return TemplateResponse(request, "book/editions/editions.html", data)
Пример #9
0
    def get(self, request):
        """view a list of requests"""
        ignored = request.GET.get("ignored", False)
        sort = request.GET.get("sort")
        sort_fields = [
            "created_date",
            "invite__times_used",
            "invite__invitees__created_date",
        ]
        # pylint: disable=consider-using-f-string
        if not sort in sort_fields + ["-{:s}".format(f) for f in sort_fields]:
            sort = "-created_date"

        requests = models.InviteRequest.objects.filter(
            ignored=ignored).order_by(sort)

        status_filters = [
            s for s in request.GET.getlist("status")
            if s in ["requested", "sent", "accepted"]
        ]

        filters = []
        if "requested" in status_filters:
            filters.append({"invite__isnull": True})
        if "sent" in status_filters:
            filters.append({"invite__isnull": False, "invite__times_used": 0})
        if "accepted" in status_filters:
            filters.append({
                "invite__isnull": False,
                "invite__times_used__gte": 1
            })

        if filters:
            requests = requests.filter(
                reduce(operator.or_, (Q(**f) for f in filters))).distinct()

        paginated = Paginator(requests, PAGE_LENGTH)

        page = paginated.get_page(request.GET.get("page"))
        data = {
            "ignored":
            ignored,
            "count":
            paginated.count,
            "requests":
            page,
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
            "sort":
            sort,
        }
        return TemplateResponse(
            request, "settings/invites/manage_invite_requests.html", data)
Пример #10
0
def get_proper_elided_page_range(paginator, number, on_each_side=3, on_ends=2):
    """
    Paginator.get_elided_page_range() takes some arguments that can't be passed in when using it in a template,
    so do it with a template tag

    https://docs.djangoproject.com/en/3.2/ref/paginator/#django.core.paginator.Paginator.get_elided_page_range
    """
    p = Paginator(paginator.object_list, paginator.per_page)
    return p.get_elided_page_range(number=number,
                                   on_each_side=on_each_side,
                                   on_ends=on_ends)
Пример #11
0
    def get(self, request, list_id, list_key):
        """display a book list"""
        book_list = get_object_or_404(models.List, id=list_id)

        embed_key = str(book_list.embed_key.hex)

        if list_key != embed_key:
            raise Http404()

        # sort_by shall be "order" unless a valid alternative is given
        sort_by = request.GET.get("sort_by", "order")
        if sort_by not in ("order", "title", "rating"):
            sort_by = "order"

        # direction shall be "ascending" unless a valid alternative is given
        direction = request.GET.get("direction", "ascending")
        if direction not in ("ascending", "descending"):
            direction = "ascending"

        directional_sort_by = {
            "order": "order",
            "title": "book__title",
            "rating": "average_rating",
        }[sort_by]
        if direction == "descending":
            directional_sort_by = "-" + directional_sort_by

        items = book_list.listitem_set.prefetch_related(
            "user", "book", "book__authors")
        if sort_by == "rating":
            items = items.annotate(average_rating=Avg(
                Coalesce("book__review__rating", 0.0),
                output_field=DecimalField(),
            ))
        items = items.filter(approved=True).order_by(directional_sort_by)

        paginated = Paginator(items, PAGE_LENGTH)

        page = paginated.get_page(request.GET.get("page"))

        data = {
            "list":
            book_list,
            "items":
            page,
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
        }
        return TemplateResponse(request, "lists/embed-list.html", data)
Пример #12
0
def makeAppointment(request):
    patient = models.Patient.objects.get(
        identity_card_no=request.session['identity_card_no'])
    if request.method == 'POST':
        # 统计已有挂号数,假如超过两个不允许再挂号
        patient = models.Patient.objects.get(
            identity_card_no=request.session['identity_card_no'])
        num = len(
            models.Appointment.objects.filter(patient=patient, isActive=True))
        # 待修改
        if num > 100:
            message = '挂号多于两个'
            return render(request, 'patient/makeAppointment.html', locals())

        appointment = models.Appointment()
        appointment.patient = models.Patient.objects.get(
            identity_card_no=request.session['identity_card_no'])
        appointment.doctor = models.Doctor.objects.get(
            identity_card_no=request.POST.get('appointment_doctor_id'))
        appointment.appointment_time = request.POST.get('appointment_time')
        appointment.appointment_date = request.POST.get('appointment_date')

        appointment.isActive = True
        appointment.save()
        request.session['appointment_id'] = appointment.id

        return redirect('/patient/makeAppointment/detail')

    departs = [depart[0] for depart in models.Doctor.department_choices]
    departs_ = [depart[1] for depart in models.Doctor.department_choices]
    depart = request.GET.get(
        'depart', departs_[0]
        if 'depart' not in request.session else request.session['depart'])
    request.session['depart'] = depart
    # print('科室', depart, departs_.index(depart))
    records = models.Doctor.objects.filter(
        department=departs[departs_.index(depart)])
    num_per_page = 5
    paginator = Paginator(records, num_per_page)
    page = request.GET.get('page', 1)
    try:
        page_obj = paginator.page(page)
    except PageNotAnInteger:
        page_obj = paginator.page(1)
    except EmptyPage:
        page_obj = paginator.page(paginator.num_pages)
    is_paginated = True if paginator.num_pages > 1 else False
    page_range = paginator.get_elided_page_range(page,
                                                 on_each_side=3,
                                                 on_ends=2)
    return render(request, 'patient/makeAppointment.html', locals())
Пример #13
0
    def get(self, request, job_id):
        """status of an import job"""
        job = get_object_or_404(models.ImportJob, id=job_id)
        if job.user != request.user:
            raise PermissionDenied()

        items = job.items.order_by("index")
        item_count = items.count() or 1

        paginated = Paginator(items, PAGE_LENGTH)
        page = paginated.get_page(request.GET.get("page"))
        manual_review_count = items.filter(fail_reason__isnull=False,
                                           book_guess__isnull=False,
                                           book__isnull=True).count()
        fail_count = items.filter(fail_reason__isnull=False,
                                  book_guess__isnull=True).count()
        pending_item_count = job.pending_items.count()
        data = {
            "job":
            job,
            "items":
            page,
            "manual_review_count":
            manual_review_count,
            "fail_count":
            fail_count,
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
            "item_count":
            item_count,
            "complete_count":
            item_count - pending_item_count,
            "percent":
            math.floor(  # pylint: disable=c-extension-no-member
                (item_count - pending_item_count) / item_count * 100),
            # hours since last import item update
            "inactive_time":
            (job.updated_date - timezone.now()).seconds / 60 / 60,
            "legacy":
            not job.mappings,
        }

        return TemplateResponse(request, "import/import_status.html", data)
Пример #14
0
def appointment(request):
    identity_card_no = request.session['identity_card_no']
    patient = models.Patient.objects.get(identity_card_no=identity_card_no)
    appointments = models.Appointment.objects.filter(patient=patient)
    num_per_page = 5
    paginator = Paginator(appointments, num_per_page)
    page = request.GET.get('page', 1)
    try:
        page_obj = paginator.page(page)
    except PageNotAnInteger:
        page_obj = paginator.page(1)
    except EmptyPage:
        page_obj = paginator.page(paginator.num_pages)
    is_paginated = True if paginator.num_pages > 1 else False
    page_range = paginator.get_elided_page_range(page,
                                                 on_each_side=3,
                                                 on_ends=2)
    return render(request, 'patient/appointment.html', locals())
Пример #15
0
    def get(self, request):
        """invite management page"""
        paginated = Paginator(
            models.SiteInvite.objects.filter(user=request.user).order_by(
                "-created_date"
            ),
            PAGE_LENGTH,
        )

        page = paginated.get_page(request.GET.get("page"))
        data = {
            "invites": page,
            "page_range": paginated.get_elided_page_range(
                page.number, on_each_side=2, on_ends=1
            ),
            "form": forms.CreateInviteForm(),
        }
        return TemplateResponse(request, "settings/invites/manage_invites.html", data)
Пример #16
0
    def get_context_data(self, **kwargs: dict) -> dict:
        context = super().get_context_data(**kwargs)

        page = self.request.GET.get("page", 1)

        team = context["team"]
        team_service = TeamService()

        context["parent_teams"] = team_service.get_all_parent_teams(team)
        context["sub_teams"] = team_service.get_all_child_teams(team)

        members = self.get_team_members(team, context["sub_teams"])
        paginator = Paginator(members, 40)
        context["team_members"] = paginator.page(page)
        context["page_numbers"] = list(paginator.get_elided_page_range(page))

        context["heading"] = self.heading

        return context
Пример #17
0
def diagnosis(request):
    if request.method == 'POST':
        request.session['diagnosis'] = request.POST.get('diagnosis')
        return redirect('/patient/diagnosis/detail')
    identity_card_no = request.session['identity_card_no']
    patient = models.Patient.objects.get(identity_card_no=identity_card_no)
    diagnosis_records = models.Diagnosis.objects.filter(patient=patient)
    num_per_page = 5
    paginator = Paginator(diagnosis_records, num_per_page)
    page = request.GET.get('page', 1)
    try:
        page_obj = paginator.page(page)
    except PageNotAnInteger:
        page_obj = paginator.page(1)
    except EmptyPage:
        page_obj = paginator.page(paginator.num_pages)
    is_paginated = True if paginator.num_pages > 1 else False
    page_range = paginator.get_elided_page_range(page,
                                                 on_each_side=3,
                                                 on_ends=2)
    return render(request, 'patient/diagnosis.html', locals())
Пример #18
0
    def get(self, request, status="federated"):
        """list of servers"""
        servers = models.FederatedServer.objects.filter(status=status)

        sort = request.GET.get("sort")
        sort_fields = ["created_date", "application_type", "server_name"]
        # pylint: disable=consider-using-f-string
        if not sort in sort_fields + ["-{:s}".format(f) for f in sort_fields]:
            sort = "-created_date"
        servers = servers.order_by(sort)

        paginated = Paginator(servers, PAGE_LENGTH)
        page = paginated.get_page(request.GET.get("page"))

        data = {
            "servers": page,
            "page_range": paginated.get_elided_page_range(
                page.number, on_each_side=2, on_ends=1
            ),
            "sort": sort,
            "form": forms.ServerForm(),
        }
        return TemplateResponse(request, "settings/federation/instance_list.html", data)
Пример #19
0
    def get(self, request, author_id):
        """landing page for an author"""
        author = get_object_or_404(models.Author, id=author_id)

        if is_api_request(request):
            return ActivitypubResponse(author.to_activity())

        books = models.Work.objects.filter(
            authors=author, editions__authors=author).distinct()

        paginated = Paginator(books, PAGE_LENGTH)
        page = paginated.get_page(request.GET.get("page"))
        data = {
            "author":
            author,
            "books":
            page,
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
        }
        return TemplateResponse(request, "author/author.html", data)
Пример #20
0
    def test_get_elided_page_range(self):
        # Paginator.validate_number() must be called:
        paginator = Paginator([1, 2, 3], 2)
        with unittest.mock.patch.object(paginator, "validate_number") as mock:
            mock.assert_not_called()
            list(paginator.get_elided_page_range(2))
            mock.assert_called_with(2)

        ELLIPSIS = Paginator.ELLIPSIS

        # Range is not elided if not enough pages when using default arguments:
        paginator = Paginator(range(10 * 100), 100)
        page_range = paginator.get_elided_page_range(1)
        self.assertIsInstance(page_range, collections.abc.Generator)
        self.assertNotIn(ELLIPSIS, page_range)
        paginator = Paginator(range(10 * 100 + 1), 100)
        self.assertIsInstance(page_range, collections.abc.Generator)
        page_range = paginator.get_elided_page_range(1)
        self.assertIn(ELLIPSIS, page_range)

        # Range should be elided if enough pages when using default arguments:
        tests = [
            # on_each_side=3, on_ends=2
            (1, [1, 2, 3, 4, ELLIPSIS, 49, 50]),
            (6, [1, 2, 3, 4, 5, 6, 7, 8, 9, ELLIPSIS, 49, 50]),
            (7, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ELLIPSIS, 49, 50]),
            (8, [1, 2, ELLIPSIS, 5, 6, 7, 8, 9, 10, 11, ELLIPSIS, 49, 50]),
            (43,
             [1, 2, ELLIPSIS, 40, 41, 42, 43, 44, 45, 46, ELLIPSIS, 49, 50]),
            (44, [1, 2, ELLIPSIS, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]),
            (45, [1, 2, ELLIPSIS, 42, 43, 44, 45, 46, 47, 48, 49, 50]),
            (50, [1, 2, ELLIPSIS, 47, 48, 49, 50]),
        ]
        paginator = Paginator(range(5000), 100)
        for number, expected in tests:
            with self.subTest(number=number):
                page_range = paginator.get_elided_page_range(number)
                self.assertIsInstance(page_range, collections.abc.Generator)
                self.assertEqual(list(page_range), expected)

        # Range is not elided if not enough pages when using custom arguments:
        tests = [
            (6, 2, 1, 1),
            (8, 1, 3, 1),
            (8, 4, 0, 1),
            (4, 1, 1, 1),
            # When on_each_side and on_ends are both <= 1 but not both == 1 it
            # is a special case where the range is not elided until an extra
            # page is added.
            (2, 0, 1, 2),
            (2, 1, 0, 2),
            (1, 0, 0, 2),
        ]
        for pages, on_each_side, on_ends, elided_after in tests:
            for offset in range(elided_after + 1):
                with self.subTest(
                        pages=pages,
                        offset=elided_after,
                        on_each_side=on_each_side,
                        on_ends=on_ends,
                ):
                    paginator = Paginator(range((pages + offset) * 100), 100)
                    page_range = paginator.get_elided_page_range(
                        1,
                        on_each_side=on_each_side,
                        on_ends=on_ends,
                    )
                    self.assertIsInstance(page_range,
                                          collections.abc.Generator)
                    if offset < elided_after:
                        self.assertNotIn(ELLIPSIS, page_range)
                    else:
                        self.assertIn(ELLIPSIS, page_range)

        # Range should be elided if enough pages when using custom arguments:
        tests = [
            # on_each_side=2, on_ends=1
            (1, 2, 1, [1, 2, 3, ELLIPSIS, 50]),
            (4, 2, 1, [1, 2, 3, 4, 5, 6, ELLIPSIS, 50]),
            (5, 2, 1, [1, 2, 3, 4, 5, 6, 7, ELLIPSIS, 50]),
            (6, 2, 1, [1, ELLIPSIS, 4, 5, 6, 7, 8, ELLIPSIS, 50]),
            (45, 2, 1, [1, ELLIPSIS, 43, 44, 45, 46, 47, ELLIPSIS, 50]),
            (46, 2, 1, [1, ELLIPSIS, 44, 45, 46, 47, 48, 49, 50]),
            (47, 2, 1, [1, ELLIPSIS, 45, 46, 47, 48, 49, 50]),
            (50, 2, 1, [1, ELLIPSIS, 48, 49, 50]),
            # on_each_side=1, on_ends=3
            (1, 1, 3, [1, 2, ELLIPSIS, 48, 49, 50]),
            (5, 1, 3, [1, 2, 3, 4, 5, 6, ELLIPSIS, 48, 49, 50]),
            (6, 1, 3, [1, 2, 3, 4, 5, 6, 7, ELLIPSIS, 48, 49, 50]),
            (7, 1, 3, [1, 2, 3, ELLIPSIS, 6, 7, 8, ELLIPSIS, 48, 49, 50]),
            (44, 1, 3, [1, 2, 3, ELLIPSIS, 43, 44, 45, ELLIPSIS, 48, 49, 50]),
            (45, 1, 3, [1, 2, 3, ELLIPSIS, 44, 45, 46, 47, 48, 49, 50]),
            (46, 1, 3, [1, 2, 3, ELLIPSIS, 45, 46, 47, 48, 49, 50]),
            (50, 1, 3, [1, 2, 3, ELLIPSIS, 49, 50]),
            # on_each_side=4, on_ends=0
            (1, 4, 0, [1, 2, 3, 4, 5, ELLIPSIS]),
            (5, 4, 0, [1, 2, 3, 4, 5, 6, 7, 8, 9, ELLIPSIS]),
            (6, 4, 0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ELLIPSIS]),
            (7, 4, 0, [ELLIPSIS, 3, 4, 5, 6, 7, 8, 9, 10, 11, ELLIPSIS]),
            (44, 4, 0,
             [ELLIPSIS, 40, 41, 42, 43, 44, 45, 46, 47, 48, ELLIPSIS]),
            (45, 4, 0, [ELLIPSIS, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]),
            (46, 4, 0, [ELLIPSIS, 42, 43, 44, 45, 46, 47, 48, 49, 50]),
            (50, 4, 0, [ELLIPSIS, 46, 47, 48, 49, 50]),
            # on_each_side=0, on_ends=1
            (1, 0, 1, [1, ELLIPSIS, 50]),
            (2, 0, 1, [1, 2, ELLIPSIS, 50]),
            (3, 0, 1, [1, 2, 3, ELLIPSIS, 50]),
            (4, 0, 1, [1, ELLIPSIS, 4, ELLIPSIS, 50]),
            (47, 0, 1, [1, ELLIPSIS, 47, ELLIPSIS, 50]),
            (48, 0, 1, [1, ELLIPSIS, 48, 49, 50]),
            (49, 0, 1, [1, ELLIPSIS, 49, 50]),
            (50, 0, 1, [1, ELLIPSIS, 50]),
            # on_each_side=0, on_ends=0
            (1, 0, 0, [1, ELLIPSIS]),
            (2, 0, 0, [1, 2, ELLIPSIS]),
            (3, 0, 0, [ELLIPSIS, 3, ELLIPSIS]),
            (48, 0, 0, [ELLIPSIS, 48, ELLIPSIS]),
            (49, 0, 0, [ELLIPSIS, 49, 50]),
            (50, 0, 0, [ELLIPSIS, 50]),
        ]
        paginator = Paginator(range(5000), 100)
        for number, on_each_side, on_ends, expected in tests:
            with self.subTest(number=number,
                              on_each_side=on_each_side,
                              on_ends=on_ends):
                page_range = paginator.get_elided_page_range(
                    number,
                    on_each_side=on_each_side,
                    on_ends=on_ends,
                )
                self.assertIsInstance(page_range, collections.abc.Generator)
                self.assertEqual(list(page_range), expected)
Пример #21
0
    def get(self, request, list_id, add_failed=False, add_succeeded=False):
        """display a book list"""
        book_list = get_object_or_404(models.List, id=list_id)
        book_list.raise_visible_to_user(request.user)

        if is_api_request(request):
            return ActivitypubResponse(book_list.to_activity(**request.GET))

        query = request.GET.get("q")
        suggestions = None

        items = book_list.listitem_set.filter(approved=True).prefetch_related(
            "user", "book", "book__authors")
        items = sort_list(request, items)

        paginated = Paginator(items, PAGE_LENGTH)

        if query and request.user.is_authenticated:
            # search for books
            suggestions = book_search.search(
                query,
                filters=[~Q(parent_work__editions__in=book_list.books.all())],
            )
        elif request.user.is_authenticated:
            # just suggest whatever books are nearby
            suggestions = request.user.shelfbook_set.filter(~Q(
                book__in=book_list.books.all()))
            suggestions = [s.book for s in suggestions[:5]]
            if len(suggestions) < 5:
                suggestions += [
                    s.default_edition for s in models.Work.objects.filter(
                        ~Q(editions__in=book_list.books.all()), ).order_by(
                            "-updated_date")
                ][:5 - len(suggestions)]

        page = paginated.get_page(request.GET.get("page"))

        embed_key = str(book_list.embed_key.hex)
        embed_url = reverse("embed-list", args=[book_list.id, embed_key])
        embed_url = request.build_absolute_uri(embed_url)

        if request.GET:
            embed_url = f"{embed_url}?{request.GET.urlencode()}"

        data = {
            "list":
            book_list,
            "items":
            page,
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
            "pending_count":
            book_list.listitem_set.filter(approved=False).count(),
            "suggested_books":
            suggestions,
            "list_form":
            forms.ListForm(instance=book_list),
            "query":
            query or "",
            "sort_form":
            forms.SortListForm(request.GET),
            "embed_url":
            embed_url,
            "add_failed":
            add_failed,
            "add_succeeded":
            add_succeeded,
        }
        return TemplateResponse(request, "lists/list.html", data)
Пример #22
0
    def get(self, request, username, shelf_identifier=None):
        """display a shelf"""
        user = get_user_from_username(request.user, username)

        is_self = user == request.user

        if is_self:
            shelves = user.shelf_set.all()
        else:
            shelves = models.Shelf.privacy_filter(
                request.user).filter(user=user).all()

        # get the shelf and make sure the logged in user should be able to see it
        if shelf_identifier:
            shelf = get_object_or_404(user.shelf_set,
                                      identifier=shelf_identifier)
            shelf.raise_visible_to_user(request.user)
            books = shelf.books
        else:
            # this is a constructed "all books" view, with a fake "shelf" obj
            FakeShelf = namedtuple(
                "Shelf", ("identifier", "name", "user", "books", "privacy"))
            books = (
                models.Edition.viewer_aware_objects(request.user).filter(
                    # privacy is ensured because the shelves are already filtered above
                    shelfbook__shelf__in=shelves).distinct())
            shelf = FakeShelf("all", _("All books"), user, books, "public")

        if is_api_request(request) and shelf_identifier:
            return ActivitypubResponse(shelf.to_activity(**request.GET))

        reviews = models.Review.objects
        if not is_self:
            reviews = models.Review.privacy_filter(request.user)

        reviews = reviews.filter(
            user=user,
            rating__isnull=False,
            book__id=OuterRef("id"),
            deleted=False,
        ).order_by("-published_date")

        reading = models.ReadThrough.objects

        reading = reading.filter(
            user=user, book__id=OuterRef("id")).order_by("start_date")

        books = books.annotate(shelved_date=Max("shelfbook__shelved_date"))
        books = books.annotate(
            rating=Subquery(reviews.values("rating")[:1]),
            start_date=Subquery(reading.values("start_date")[:1]),
            finish_date=Subquery(reading.values("finish_date")[:1]),
            author=Subquery(
                models.Book.objects.filter(
                    id=OuterRef("id")).values("authors__name")[:1]),
        ).prefetch_related("authors")

        books = sort_books(books, request.GET.get("sort"))

        paginated = Paginator(
            books,
            PAGE_LENGTH,
        )
        page = paginated.get_page(request.GET.get("page"))
        data = {
            "user":
            user,
            "is_self":
            is_self,
            "shelves":
            shelves,
            "shelf":
            shelf,
            "books":
            page,
            "edit_form":
            forms.ShelfForm(instance=shelf if shelf_identifier else None),
            "create_form":
            forms.ShelfForm(),
            "sort":
            request.GET.get("sort"),
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
        }

        return TemplateResponse(request, "shelf/shelf.html", data)
Пример #23
0
class Datagrid(metaclass=DatagridMeta):
    def __init__(
        self,
        queryset,
        *,
        parent_model: DjangoModel = None,
        paginate: bool = True,
        per_page: int = 20,
        page: int = 1,
        more_url: str = None,
        request: HttpRequest,
        page_parameter_name: str = "page",
    ):
        self.parent_model = parent_model
        self.page_parameter_name = page_parameter_name
        self.paginator = Paginator(queryset, per_page)
        self.page = self.paginator.page(page)
        self.paginate = paginate
        self.more_url = more_url
        self.request = request

    def __str__(self):
        """Render the datagrid"""

        template = loader.get_template(self.template)

        return template.render(self.context())

    @property
    def template(self):
        return "ui/datagrid/datagrid.html"

    def context(self):
        rows = []
        for item in self.page:
            bound_columns = []
            for column in self._meta.columns:
                bound_columns.append(column.bind(grid=self, model=item))

            rows.append(bound_columns)
        return {
            "title": get_item_value(None,
                                    "title",
                                    container=self,
                                    exclude=Column),
            "actions": [action.bind(self) for action in self._meta.actions],
            "rows": rows,
            "columns": self._meta.columns,
            "pagination": {
                "display":
                self.paginate,
                "page_parameter":
                self.page_parameter_name,
                "item_label":
                _("Item") if self.paginator.count == 1 else _("items"),
                "previous_page_number":
                self.page.previous_page_number()
                if self.page.has_previous() else None,
                "next_page_number":
                self.page.next_page_number() if self.page.has_next() else None,
                "current_page_number":
                self.page.number,
                "current_page_count":
                len(self.page),
                "total_count":
                self.total_count,
                "total_page_count":
                self.total_page_count,
                "range":
                self.paginator.get_elided_page_range(self.page.number,
                                                     on_ends=1),
                "start_index":
                self.start_index,
                "end_index":
                self.end_index,
            },
            "more_url": self.more_url,
        }

    @property
    def total_count(self):
        return self.paginator.count

    @property
    def total_page_count(self):
        return self.paginator.num_pages

    @property
    def start_index(self):
        return self.page.start_index()

    @property
    def end_index(self):
        return self.page.end_index()

    def __len__(self):
        return self.paginator.count
Пример #24
0
    def get(self, request, list_id):
        """display a book list"""
        book_list = get_object_or_404(models.List, id=list_id)
        if not book_list.visible_to_user(request.user):
            return HttpResponseNotFound()

        if is_api_request(request):
            return ActivitypubResponse(book_list.to_activity(**request.GET))

        query = request.GET.get("q")
        suggestions = None

        # sort_by shall be "order" unless a valid alternative is given
        sort_by = request.GET.get("sort_by", "order")
        if sort_by not in ("order", "title", "rating"):
            sort_by = "order"

        # direction shall be "ascending" unless a valid alternative is given
        direction = request.GET.get("direction", "ascending")
        if direction not in ("ascending", "descending"):
            direction = "ascending"

        directional_sort_by = {
            "order": "order",
            "title": "book__title",
            "rating": "average_rating",
        }[sort_by]
        if direction == "descending":
            directional_sort_by = "-" + directional_sort_by

        items = book_list.listitem_set
        if sort_by == "rating":
            items = items.annotate(average_rating=Avg(
                Coalesce("book__review__rating", 0.0),
                output_field=DecimalField(),
            ))
        items = items.filter(approved=True).order_by(directional_sort_by)

        paginated = Paginator(items, PAGE_LENGTH)

        if query and request.user.is_authenticated:
            # search for books
            suggestions = connector_manager.local_search(
                query,
                raw=True,
                filters=[~Q(parent_work__editions__in=book_list.books.all())],
            )
        elif request.user.is_authenticated:
            # just suggest whatever books are nearby
            suggestions = request.user.shelfbook_set.filter(~Q(
                book__in=book_list.books.all()))
            suggestions = [s.book for s in suggestions[:5]]
            if len(suggestions) < 5:
                suggestions += [
                    s.default_edition for s in models.Work.objects.filter(
                        ~Q(editions__in=book_list.books.all()), ).order_by(
                            "-updated_date")
                ][:5 - len(suggestions)]

        page = paginated.get_page(request.GET.get("page"))
        data = {
            "list":
            book_list,
            "items":
            page,
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
            "pending_count":
            book_list.listitem_set.filter(approved=False).count(),
            "suggested_books":
            suggestions,
            "list_form":
            forms.ListForm(instance=book_list),
            "query":
            query or "",
            "sort_form":
            forms.SortListForm({
                "direction": direction,
                "sort_by": sort_by
            }),
        }
        return TemplateResponse(request, "lists/list.html", data)
Пример #25
0
    def get(self, request, username, shelf_identifier=None):
        """display a shelf"""
        user = get_user_from_username(request.user, username)

        shelves = privacy_filter(request.user, user.shelf_set)

        # get the shelf and make sure the logged in user should be able to see it
        if shelf_identifier:
            try:
                shelf = user.shelf_set.get(identifier=shelf_identifier)
            except models.Shelf.DoesNotExist:
                return HttpResponseNotFound()
            if not shelf.visible_to_user(request.user):
                return HttpResponseNotFound()
            books = shelf.books
        # this is a constructed "all books" view, with a fake "shelf" obj
        else:
            FakeShelf = namedtuple(
                "Shelf", ("identifier", "name", "user", "books", "privacy"))
            books = models.Edition.objects.filter(
                # privacy is ensured because the shelves are already filtered above
                shelfbook__shelf__in=shelves.all()).distinct()
            shelf = FakeShelf("all", _("All books"), user, books, "public")

        if is_api_request(request):
            return ActivitypubResponse(shelf.to_activity(**request.GET))

        reviews = privacy_filter(
            request.user,
            models.Review.objects.filter(
                user=user,
                rating__isnull=False,
                book__id=OuterRef("id"),
            ),
        ).order_by("-published_date")

        books = books.annotate(rating=Subquery(reviews.values("rating")[:1]))

        paginated = Paginator(
            books.order_by("-updated_date"),
            PAGE_LENGTH,
        )

        page = paginated.get_page(request.GET.get("page"))
        data = {
            "user":
            user,
            "is_self":
            request.user == user,
            "shelves":
            shelves.all(),
            "shelf":
            shelf,
            "books":
            page,
            "page_range":
            paginated.get_elided_page_range(page.number,
                                            on_each_side=2,
                                            on_ends=1),
        }

        return TemplateResponse(request, "user/shelf/shelf.html", data)
Пример #26
0
def get_proper_elided_page_range(p, number, on_each_side=3, on_ends=2):
    """Paginator get_proper_elided_page_range override"""
    paginator = Paginator(p.object_list, p.per_page, p.orphans)
    return paginator.get_elided_page_range(number=number,
                                           on_each_side=on_each_side,
                                           on_ends=on_ends)