Phase 2 评审修复: P0 min_score+&q=500 (ORM→list 顺序) + P1 场景分页(20/page) + P2 文档同步 + 36 tests

This commit is contained in:
ila
2026-07-06 23:04:55 +08:00
parent cff3c64c19
commit 714d218eb2
6 changed files with 218 additions and 6 deletions
+11 -5
View File
@@ -31,12 +31,18 @@ class ScenarioPage(Page):
def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
context["projects"] = (
projects = (
SkeletonProjectPage.objects.live()
.filter(scenarios=self)
.prefetch_related("languages", "scenarios")
.order_by("-first_published_at")
)
paginator = Paginator(projects, 20)
page = request.GET.get("page", "1")
try:
context["projects"] = paginator.page(int(page))
except (ValueError, EmptyPage):
context["projects"] = paginator.page(1)
return context
class Meta:
@@ -148,6 +154,10 @@ class ProjectIndexPage(Page):
projects = projects.filter(frameworks__slug=framework)
if database:
projects = projects.filter(databases__slug=database)
if q:
projects = projects.filter(
Q(title__icontains=q) | Q(summary__icontains=q)
)
try:
score_val = int(min_score)
if 0 <= score_val <= 30:
@@ -156,10 +166,6 @@ class ProjectIndexPage(Page):
]
except (ValueError, TypeError):
pass
if q:
projects = projects.filter(
Q(title__icontains=q) | Q(summary__icontains=q)
)
paginator = Paginator(projects, 20)
page = request.GET.get("page", "1")
+12
View File
@@ -22,6 +22,18 @@
</a>
{% endfor %}
</div>
{% if projects.paginator.num_pages > 1 %}
<nav class="pagination">
{% if projects.has_previous %}
<a href="?page={{ projects.previous_page_number }}">&laquo; Prev</a>
{% endif %}
<span class="current">Page {{ projects.number }} of {{ projects.paginator.num_pages }}</span>
{% if projects.has_next %}
<a href="?page={{ projects.next_page_number }}">Next &raquo;</a>
{% endif %}
</nav>
{% endif %}
{% else %}
{% include "includes/empty_state.html" with message="No projects found in this scenario." %}
{% endif %}
+55
View File
@@ -75,6 +75,46 @@ class ScenarioPageTests(PageTreeMixin, TestCase):
self.assertContains(response, "Nothing here yet")
class ScenarioPaginationTests(PageTreeMixin, TestCase):
@classmethod
def setUpTestData(cls):
cls.setUpPageTree()
cls.lang = Language.objects.create(name="Python", slug="python")
for i in range(21):
project = SkeletonProjectPage(
title=f"Pagination Project {i+1}",
slug=f"pagination-project-{i+1}",
summary=f"Project {i+1} for pagination test",
github_url="https://github.com/test/pagination",
maturity="stable",
recommended_for="Testing",
structure_score=3, docs_score=3, tests_score=3,
example_score=3, dependency_score=3, incremental_score=3,
)
cls.project_index.add_child(instance=project)
project.languages.add(cls.lang)
project.scenarios.add(cls.scenario)
project.save()
def test_first_page_has_20_items(self):
resp = self.client.get(self.scenario.url)
self.assertEqual(resp.status_code, 200)
self.assertContains(resp, "Pagination Project 1")
self.assertContains(resp, "Pagination Project 20")
self.assertNotContains(resp, "Pagination Project 21")
def test_second_page_has_1_item(self):
resp = self.client.get(f"{self.scenario.url}?page=2")
self.assertEqual(resp.status_code, 200)
self.assertNotContains(resp, "Pagination Project 1")
self.assertContains(resp, "Pagination Project 21")
def test_invalid_page_falls_back_to_first(self):
resp = self.client.get(f"{self.scenario.url}?page=abc")
self.assertEqual(resp.status_code, 200)
self.assertContains(resp, "Pagination Project 1")
class ProjectFilterTests(PageTreeMixin, TestCase):
@classmethod
def setUpTestData(cls):
@@ -135,6 +175,21 @@ class ProjectFilterTests(PageTreeMixin, TestCase):
resp = self.client.get("/projects/?min_score=abc&page=xyz")
self.assertEqual(resp.status_code, 200)
def test_combined_filters_return_200(self):
resp = self.client.get(
"/projects/?language=python&framework=django&min_score=18&q=Django"
)
self.assertEqual(resp.status_code, 200)
self.assertContains(resp, "Django Project")
self.assertNotContains(resp, "Go Project")
def test_combined_filters_no_results_returns_empty_state(self):
resp = self.client.get(
"/projects/?language=go&framework=django&min_score=18"
)
self.assertEqual(resp.status_code, 200)
self.assertContains(resp, "No projects match")
class SkeletonProjectDetailTests(PageTreeMixin, TestCase):
@classmethod