mirror of
https://github.com/boostorg/website-v2.git
synced 2026-02-27 05:32:08 +00:00
Merge pull request #85 from revsys/filter-by-category
Filter library results by category
This commit is contained in:
8
libraries/forms.py
Normal file
8
libraries/forms.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from django.forms import ModelForm
|
||||
from .models import Library, Category
|
||||
|
||||
|
||||
class LibraryForm(ModelForm):
|
||||
class Meta:
|
||||
model = Library
|
||||
fields = ["categories"]
|
||||
@@ -3,6 +3,11 @@ from fastcore.xtras import dict2obj
|
||||
from model_bakery import baker
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def category(db):
|
||||
return baker.make("libraries.Category", name="Math", slug="math")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def library(db):
|
||||
return baker.make(
|
||||
|
||||
6
libraries/tests/test_forms.py
Normal file
6
libraries/tests/test_forms.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from ..forms import LibraryForm
|
||||
|
||||
|
||||
def test_library_form_success(tp, library, category):
|
||||
form = LibraryForm(data={"categories": [category]})
|
||||
assert form.is_valid() is True
|
||||
@@ -7,6 +7,25 @@ def test_library_list(library, tp):
|
||||
tp.response_200(res)
|
||||
|
||||
|
||||
def test_library_list_select_category(library, category, tp):
|
||||
"""POST /libraries/ to submit a category redirects to the libraries-by-category page"""
|
||||
res = tp.post("libraries", data={"categories": category.pk})
|
||||
tp.response_302(res)
|
||||
|
||||
|
||||
def test_libraries_by_category(tp, library, category):
|
||||
"""GET /libraries-by-category/{slug}/"""
|
||||
baker.make("libraries.Library", name="Sample")
|
||||
library.categories.add(category)
|
||||
res = tp.get("libraries-by-category", category.slug)
|
||||
tp.response_200(res)
|
||||
assert "library_list" in res.context
|
||||
assert len(res.context["library_list"]) == 1
|
||||
assert library in res.context["library_list"]
|
||||
assert "category" in res.context
|
||||
assert res.context["category"] == category
|
||||
|
||||
|
||||
def test_library_detail(library, tp):
|
||||
"""GET /libraries/{repo}/"""
|
||||
url = tp.reverse("library-detail", library.slug)
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
from django.views.generic import DetailView, ListView
|
||||
import structlog
|
||||
|
||||
from django.shortcuts import redirect
|
||||
from django.views.generic import DetailView, ListView
|
||||
from django.views.generic.edit import FormMixin
|
||||
|
||||
from .forms import LibraryForm
|
||||
from .models import Category, Issue, Library, PullRequest
|
||||
|
||||
logger = structlog.get_logger()
|
||||
|
||||
|
||||
class CategoryMixin:
|
||||
def get_context_data(self, **kwargs):
|
||||
@@ -10,15 +17,26 @@ class CategoryMixin:
|
||||
return context
|
||||
|
||||
|
||||
class LibraryList(CategoryMixin, ListView):
|
||||
class LibraryList(CategoryMixin, FormMixin, ListView):
|
||||
"""List all of our libraries by name"""
|
||||
|
||||
form_class = LibraryForm
|
||||
paginate_by = 25
|
||||
queryset = (
|
||||
Library.objects.prefetch_related("authors", "categories").all().order_by("name")
|
||||
)
|
||||
template_name = "libraries/list.html"
|
||||
|
||||
def post(self, request):
|
||||
"""User has submitted a form and will be redirected to the right results"""
|
||||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
category = form.cleaned_data["categories"][0]
|
||||
return redirect("libraries-by-category", category=category.slug)
|
||||
else:
|
||||
logger.info("library_list_invalid_category")
|
||||
return super().get(request)
|
||||
|
||||
|
||||
class LibraryByLetter(CategoryMixin, ListView):
|
||||
"""List all of our libraries that begin with a certain letter"""
|
||||
@@ -42,6 +60,17 @@ class LibraryByCategory(CategoryMixin, ListView):
|
||||
paginate_by = 25
|
||||
template_name = "libraries/list.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data()
|
||||
category_slug = self.kwargs.get("category")
|
||||
if category_slug:
|
||||
try:
|
||||
category = Category.objects.get(slug=category_slug)
|
||||
context["category"] = category
|
||||
except Category.DoesNotExist:
|
||||
logger.info("libraries_by_category_view_category_not_found")
|
||||
return context
|
||||
|
||||
def get_queryset(self):
|
||||
category = self.kwargs.get("category")
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{% block content %}
|
||||
<!-- Breadcrumb used on filtered views -->
|
||||
<div class="p-3 md:p-0">
|
||||
<a class="text-orange" href="{% url "libraries" %}">Libraries</a> > Categorized
|
||||
<a class="text-orange" href="{% url "libraries" %}">Libraries</a> > Categorized{% if category %} > <a class="text-orange" href="{% url "libraries-by-category" category.slug %}">{{ category.name }}</a>{% endif %}
|
||||
</div>
|
||||
<!-- end breadcrumb -->
|
||||
|
||||
@@ -43,14 +43,21 @@
|
||||
</span>
|
||||
<input type="search" name="q" class="w-full md:w-1/3 text-sm text-white bg-charcoal focus:text-charcoal text-orange px-3 py-2 rounded-md" type="text" value="" placeholder="Search Library" />
|
||||
</div>
|
||||
<div>
|
||||
<select class="mb-3 md:mb-0 w-full md:w-auto cursor-pointer block sm:inline-block text-sm uppercase rounded-md bg-black text-orange border border-slate pl-5 pr-11 py-3 mr-3">
|
||||
<option>Filter by category</option>
|
||||
{% for c in categories %}
|
||||
<option value="{{c.name}}">{{ c.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Form to select a category -->
|
||||
<form action="/libraries/" method="post">
|
||||
{% csrf_token %}
|
||||
<div>
|
||||
<label for="id_categories" hidden="true">Categories:</label>
|
||||
<select name="categories" class="mb-3 md:mb-0 w-full md:w-auto cursor-pointer block sm:inline-block text-sm uppercase rounded-md bg-black text-orange border border-slate pl-5 pr-11 py-3 mr-3" id="id_categories">
|
||||
<option>Filter by category</option>
|
||||
{% for c in categories %}
|
||||
<option value="{{ c.pk }}" {% if category == c %}selected="selected"{% endif %}>{{ c.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<input type="submit" value="Submit" style="color: red">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user