Skip to content

Commit b6a284e

Browse files
Merge pull request #129 from valerymelou/fix_pypi_release
Release 0.2.1
2 parents 047b5ff + 0ce26df commit b6a284e

File tree

9 files changed

+87
-26
lines changed

9 files changed

+87
-26
lines changed

HISTORY.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@
33
History
44
-------
55

6+
0.2.1 (2024-06-07)
7+
+++++++++++++++++
8+
Important changes
9+
10+
* inactive_class renamed to css_inactive_class.
11+
612
0.2.0 (2024-06-06)
713
+++++++++++++++++
8-
Breaking changes
914

1015
* Update build tools to be using Poetry.
1116
* Dropped support for old Django versions, now officially supporting only: Django 4.0, 4.1, 4.2, 5.0.

README.rst

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@ or:
6969

7070
<a href="{% url 'view-name' %}" class="{% active_link 'view-name' css_class='custom-class' %}">Menu item</a>
7171

72+
You can also define an inactive custom css class, that is triggered when a link is deemed not active:
73+
74+
.. code-block:: html
75+
76+
<a href="{% url 'view-name' %}" class="{% active_link 'view-name' 'custom-class' 'not-active' %}">Menu item</a>
77+
78+
or:
79+
80+
.. code-block:: html
81+
82+
<a href="{% url 'view-name' %}" class="{% active_link 'view-name' css_class='custom-class' css_inactive_class='not-active' %}">Menu item</a>
83+
7284
By default ``active_link`` will not perform a strict match. If you want to add the ``active`` class only in case of a strict match pass the ``strict`` argument to the tag:
7385

7486
.. code-block:: html
@@ -79,14 +91,15 @@ Replace ``view-name`` with the name of your view (including namespaces).
7991

8092
Settings
8193
--------
82-
You can override the default active class and strict mode with the settings ``ACTIVE_LINK_CSS_CLASS`` and ``ACTIVE_LINK_STRICT``.
83-
84-
===================== ==================================================== =============
85-
Key Description Default Value
86-
===================== ==================================================== =============
87-
ACTIVE_LINK_CSS_CLASS Active class to use. `active`
88-
ACTIVE_LINK_STRICT Designates whether to perform a strict match or not. `False`
89-
===================== ==================================================== =============
94+
You can override the default active class and strict mode with the settings ``ACTIVE_LINK_CSS_CLASS``, ``ACTIVE_LINK_CSS_INACTIVE_CLASS`` and ``ACTIVE_LINK_STRICT``.
95+
96+
============================== ==================================================== =============
97+
Key Description Default Value
98+
============================== ==================================================== =============
99+
ACTIVE_LINK_CSS_CLASS Active class to use. `active`
100+
ACTIVE_LINK_CSS_INACTIVE_CLASS Inactive class to use.
101+
ACTIVE_LINK_STRICT Designates whether to perform a strict match or not. `False`
102+
============================== ==================================================== =============
90103

91104
For more usage examples, please check the full documentation at https://django-active-link.readthedocs.io.
92105

active_link/templatetags/active_link_tags.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,40 @@
88

99
@register.simple_tag(takes_context=True)
1010
def active_link(
11-
context, viewnames, css_class=None, inactive_class="", strict=None, *args, **kwargs
11+
context,
12+
viewnames,
13+
css_class=None,
14+
css_inactive_class="",
15+
strict=None,
16+
*args,
17+
**kwargs
1218
):
1319
"""
1420
Renders the given CSS class if the request path matches the path of the view.
1521
:param context: The context where the tag was called. Used to access the request object.
1622
:param viewnames: The name of the view or views separated by || (include namespaces if any).
17-
:param css_class: The CSS class to render.
18-
:param inactive_class: The CSS class to render if the views is not active.
23+
:param css_class: The CSS class to render if the view is active.
24+
:param css_inactive_class: The CSS class to render if the view is not active.
1925
:param strict: If True, the tag will perform an exact match with the request path.
2026
:return:
2127
"""
2228
if css_class is None:
2329
css_class = getattr(settings, "ACTIVE_LINK_CSS_CLASS", "active")
2430

31+
if css_inactive_class == "":
32+
css_inactive_class = getattr(settings, "ACTIVE_LINK_CSS_INACTIVE_CLASS", "")
33+
2534
if strict is None:
2635
strict = getattr(settings, "ACTIVE_LINK_STRICT", False)
2736

2837
request = context.get("request")
2938
if request is None:
3039
# Can't work without the request object.
31-
return inactive_class
40+
return css_inactive_class
3241

33-
if request.resolver_match is not None:
42+
if request.resolver_match.kwargs != {}:
3443
# Capture the url kwargs to reverse against
35-
request_kwargs = request.resolver_match.kwargs
36-
kwargs.update(request_kwargs)
44+
kwargs.update(request.resolver_match.kwargs)
3745

3846
active = False
3947
views = viewnames.split("||")
@@ -54,4 +62,4 @@ def active_link(
5462
if active:
5563
return css_class
5664

57-
return inactive_class
65+
return css_inactive_class

docs/usage.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ To use Django Active Link in a project, add it to your `INSTALLED_APPS`:
1212
...
1313
)
1414
15-
**IMPORTANT**: Django Active Link requires that the current request object is available in your template's context. This means you must be using a `RequestContext` when rendering your template, and `django.core.context_processors.request` must be in your `TEMPLATE_CONTEXT_PROCESSORS` setting. See [the documentation](https://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext) for more information.
15+
**IMPORTANT**: Django Active Link requires that the current request object is available in your template's context. This means you must be using a `RequestContext` when rendering your template, and `django.template.context_processors.request` must be in your `TEMPLATE_CONTEXT_PROCESSORS` setting. See [the documentation](https://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext) for more information.
1616

1717
To use the `active_link` template tag you need to load `active_link_tags` templatetags library:
1818

@@ -30,4 +30,9 @@ You can also match views that take arguments. For example:
3030

3131
<a href="{% url 'view-name' %}" class="{% active_link 'view-name-with-args' pk=12 slug='simple-slug' %}">Menu item</a>
3232

33+
You can also define an inactive custom css class, that is triggered when a link is deemed not active:
34+
35+
.. code-block:: html
36+
<a href="{% url 'view-name' %}" class="{% active_link 'view-name' 'custom-class' 'not-active' %}">Menu item</a>
37+
3338
Replace `view-name` with the name of your view (including namespaces).

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "django-active-link"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
description = "The best and simplest way to highlight active links in your Django app."
55
license = "BSD-3-Clause"
66
authors = [
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{% load active_link_tags %}
2+
<!DOCTYPE html>
3+
<html lang="en">
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Simple test</title>
8+
</head>
9+
<body>
10+
<div class="{% active_link 'detailed-action' css_inactive_class='not-active' %}">
11+
12+
</div>
13+
</body>
14+
</html>

tests/templates/simple.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<title>Simple test</title>
88
</head>
99
<body>
10-
<div class="{% active_link 'simple' %}">
10+
<div class="{% active_link 'simple' css_inactive_class='not-active' %}">
1111

1212
</div>
1313
</body>

tests/test_tags.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from django.template import Context, Template
1+
from django.template.loader import render_to_string
22
from django.test import Client, TestCase, override_settings
33
from django.urls import reverse
44

@@ -17,10 +17,12 @@ def reverse_helper(self, reverse_url_string, kwargs=None):
1717
return content
1818

1919
def test_no_request(self):
20-
template = Template("simple.html")
21-
context = Context({"request": None})
22-
html = template.render(context)
23-
self.assertNotIn("active", html)
20+
html = render_to_string("simple.html")
21+
self.assertNotIn('<div class="active">', html)
22+
23+
def test_no_request_inactive_class(self):
24+
html = render_to_string("simple.html")
25+
self.assertInHTML('<div class="not-active">', html)
2426

2527
def test_match_defaults(self):
2628
content = self.reverse_helper("simple")
@@ -39,10 +41,15 @@ def test_custom_class(self):
3941
self.assertInHTML('<div class="my-active-class">', content)
4042

4143
@override_settings(ACTIVE_LINK_CSS_CLASS="my-active-class")
42-
def test_settings_css_class(self):
44+
def test_settings_css_active_class(self):
4345
content = self.reverse_helper("simple")
4446
self.assertInHTML('<div class="my-active-class">', content)
4547

48+
@override_settings(ACTIVE_LINK_CSS_INACTIVE_CLASS="my-not-active-class")
49+
def test_settings_css_not_active_class(self):
50+
content = self.reverse_helper("simple-strict-no-match")
51+
self.assertInHTML('<div class="my-not-active-class">', content)
52+
4653
@override_settings(ACTIVE_LINK_STRICT=True)
4754
def test_settings_strict(self):
4855
content = self.reverse_helper("simple-settings-strict")
@@ -55,3 +62,7 @@ def test_match_url_with_kwargs(self):
5562
def test_match_url_with_kwargs_with_multiple(self):
5663
content = self.reverse_helper("detailed-action-multiple", {"pk": 12})
5764
self.assertInHTML('<div class="active">', content)
65+
66+
def test_match_url_with_kwargs_with_multiple_not_active(self):
67+
content = self.reverse_helper("detailed-action-not-active", {"pk": 12})
68+
self.assertInHTML('<div class="not-active">', content)

tests/urls.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
TemplateView.as_view(template_name="detailed_action_kwargs.html"),
3232
name="detailed-action",
3333
),
34+
path(
35+
r"detailed/action/not-active/<int:pk>/",
36+
TemplateView.as_view(template_name="detailed_action_kwargs_not_active.html"),
37+
name="detailed-action-not-active",
38+
),
3439
path(
3540
r"detailed/action/multiple/<int:pk>/",
3641
TemplateView.as_view(template_name="detailed_action_kwargs_multiple.html"),

0 commit comments

Comments
 (0)