diff --git a/djpress/migrations/0004_rename_name_category_title_category_menu_order.py b/djpress/migrations/0004_rename_name_category_title_category_menu_order.py
new file mode 100644
index 0000000..9db36ad
--- /dev/null
+++ b/djpress/migrations/0004_rename_name_category_title_category_menu_order.py
@@ -0,0 +1,22 @@
+# Generated by Django 5.0.6 on 2024-06-21 03:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("djpress", "0003_post_menu_order"),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name="category",
+ old_name="name",
+ new_name="title",
+ ),
+ migrations.AddField(
+ model_name="category",
+ name="menu_order",
+ field=models.IntegerField(default=0),
+ ),
+ ]
diff --git a/djpress/models/category.py b/djpress/models/category.py
index d726aa1..5a2dfdd 100644
--- a/djpress/models/category.py
+++ b/djpress/models/category.py
@@ -56,9 +56,10 @@ def get_category_by_slug(self: "CategoryManager", slug: str) -> "Category":
class Category(models.Model):
"""Category model."""
- name = models.CharField(max_length=100)
+ title = models.CharField(max_length=100)
slug = models.SlugField(unique=True, blank=True)
description = models.TextField(blank=True)
+ menu_order = models.IntegerField(default=0)
# Custom Manager
objects: "CategoryManager" = CategoryManager()
@@ -71,14 +72,14 @@ class Meta:
def __str__(self: "Category") -> str:
"""Return the string representation of the category."""
- return self.name
+ return self.title
def save(self: "Category", *args, **kwargs) -> None: # noqa: ANN002, ANN003
"""Override the save method to auto-generate the slug."""
if not self.slug:
- self.slug = slugify(self.name)
+ self.slug = slugify(self.title)
if not self.slug or self.slug.strip("-") == "":
- msg = "Invalid name. Unable to generate a valid slug."
+ msg = "Invalid title. Unable to generate a valid slug."
raise ValueError(msg)
try:
diff --git a/djpress/templates/djpress/index.html b/djpress/templates/djpress/index.html
index faecdef..61b33f6 100644
--- a/djpress/templates/djpress/index.html
+++ b/djpress/templates/djpress/index.html
@@ -17,7 +17,7 @@
{% blog_title_link %}
- {% category_name "h1" pre_text="View Posts in the " post_text=" Category" %}
+ {% category_title "h1" pre_text="View Posts in the " post_text=" Category" %}
{% author_name "h1" pre_text="View Posts by " %}
{% if post %}
diff --git a/djpress/templatetags/djpress_tags.py b/djpress/templatetags/djpress_tags.py
index c0d44a8..1e4a9b2 100644
--- a/djpress/templatetags/djpress_tags.py
+++ b/djpress/templatetags/djpress_tags.py
@@ -70,7 +70,7 @@ def get_categories() -> models.QuerySet[Category] | None:
Returns:
models.QuerySet[Category]: All categories.
"""
- return Category.objects.get_categories()
+ return Category.objects.get_categories().order_by("menu_order").order_by("title")
@register.simple_tag
@@ -165,7 +165,7 @@ def blog_page_title(
post: Post | None = context.get("post")
if category:
- page_title = category.name
+ page_title = category.title
elif author:
page_title = get_author_display_name(author)
@@ -329,7 +329,7 @@ def post_category_link(category: Category, link_class: str = "") -> str:
link_class: The CSS class(es) for the link.
"""
if not settings.CATEGORY_PATH_ENABLED:
- return category.name
+ return category.title
return mark_safe(category_link(category, link_class))
@@ -452,14 +452,14 @@ def post_content(
@register.simple_tag(takes_context=True)
-def category_name(
+def category_title(
context: Context,
outer: str = "",
outer_class: str = "",
pre_text: str = "",
post_text: str = "",
) -> str:
- """Return the name of a category.
+ """Return the title of a category.
Expects there to be an `category` in the context set to a Category object. If
there's no category in the context or category is not a Category object, then retun
@@ -470,11 +470,11 @@ def category_name(
context: The context.
outer: The outer HTML tag for the category.
outer_class: The CSS class(es) for the outer tag.
- pre_text: The text to prepend to the category name.
- post_text: The text to append to the category name.
+ pre_text: The text to prepend to the category title.
+ post_text: The text to append to the category title.
Returns:
- str: The name of the category formatted with the outer tag and class if
+ str: The title of the category formatted with the outer tag and class if
provided.
"""
category: Category | None = context.get("category")
@@ -485,7 +485,7 @@ def category_name(
allowed_outer_tags = ["h1", "h2", "h3", "h4", "h5", "h6", "p", "div", "span"]
outer_class = f' class="{outer_class}"' if outer_class else ""
- output = category.name
+ output = category.title
if pre_text:
output = f"{pre_text}{output}"
diff --git a/djpress/templatetags/helpers.py b/djpress/templatetags/helpers.py
index dc21489..2eb115c 100644
--- a/djpress/templatetags/helpers.py
+++ b/djpress/templatetags/helpers.py
@@ -68,8 +68,8 @@ def category_link(category: Category, link_class: str = "") -> str:
link_class_html = f' class="{link_class}"' if link_class else ""
return (
- f'{ category.name }'
+ f'{ category.title }'
)
diff --git a/pyproject.toml b/pyproject.toml
index ccf3a76..9332cdd 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "djpress"
-version = "0.7.2"
+version = "0.8.0"
authors = [{ name = "Stuart Maxwell", email = "stuart@amanzi.nz" }]
description = "A blog application for Django sites, inspired by classic WordPress."
readme = "README.md"
diff --git a/tests/test_cache_category.py b/tests/test_cache_category.py
index 9afd341..d1be1a4 100644
--- a/tests/test_cache_category.py
+++ b/tests/test_cache_category.py
@@ -15,8 +15,8 @@ def test_get_cached_categories():
assert settings.CACHE_CATEGORIES is True
# Create some test categories
- Category.objects.create(name="Category 1")
- Category.objects.create(name="Category 2")
+ Category.objects.create(title="Category 1")
+ Category.objects.create(title="Category 2")
# Call the get_cached_categories method
queryset = Category.objects._get_cached_categories()
@@ -38,7 +38,7 @@ def test_cache_invalidation_on_save():
assert settings.CACHE_CATEGORIES is True
# Create a test category
- category = Category.objects.create(name="Category 1")
+ category = Category.objects.create(title="Category 1")
# Call the get_cached_categories method
queryset = Category.objects._get_cached_categories()
@@ -49,7 +49,7 @@ def test_cache_invalidation_on_save():
assert len(queryset) == 1
# Modify the category and save it
- category.name = "Updated Category"
+ category.title = "Updated Category"
category.save()
# Assert that the cache is invalidated
@@ -63,7 +63,7 @@ def test_cache_invalidation_on_save():
cached_queryset2 = cache.get(CATEGORY_CACHE_KEY)
assert cached_queryset2 is not None
assert len(queryset2) == 1
- assert queryset2[0].name == "Updated Category"
+ assert queryset2[0].title == "Updated Category"
@pytest.mark.django_db
@@ -72,7 +72,7 @@ def test_cache_invalidation_on_delete():
assert settings.CACHE_CATEGORIES is True
# Create a test category
- category = Category.objects.create(name="Category 1")
+ category = Category.objects.create(title="Category 1")
# Call the get_cached_categories method
queryset = Category.objects._get_cached_categories()
@@ -104,8 +104,8 @@ def test_cache_get_category_by_slug():
# Confirm the settings in settings_testing.py
assert settings.CACHE_CATEGORIES is True
- category1 = Category.objects.create(name="Category 1", slug="category-1")
- category2 = Category.objects.create(name="Category 2", slug="category-2")
+ category1 = Category.objects.create(title="Category 1", slug="category-1")
+ category2 = Category.objects.create(title="Category 2", slug="category-2")
category = Category.objects.get_category_by_slug("category-1")
@@ -119,8 +119,8 @@ def test_cache_get_category_by_slug_not_in_cache():
# Confirm the settings in settings_testing.py
assert settings.CACHE_CATEGORIES is True
- category1 = Category.objects.create(name="Category 1", slug="category-1")
- category2 = Category.objects.create(name="Category 2", slug="category-2")
+ category1 = Category.objects.create(title="Category 1", slug="category-1")
+ category2 = Category.objects.create(title="Category 2", slug="category-2")
# Call the get_cached_categories method
queryset = Category.objects._get_cached_categories()
diff --git a/tests/test_models_category.py b/tests/test_models_category.py
index 35a77d8..599fe0d 100644
--- a/tests/test_models_category.py
+++ b/tests/test_models_category.py
@@ -8,8 +8,8 @@
@pytest.mark.django_db
def test_category_model():
- category = Category.objects.create(name="Test Category", slug="test-category")
- assert category.name == "Test Category"
+ category = Category.objects.create(title="Test Category", slug="test-category")
+ assert category.title == "Test Category"
assert category.slug == "test-category"
assert str(category) == "Test Category"
@@ -17,7 +17,7 @@ def test_category_model():
@pytest.mark.django_db
def test_category_save_slug_generation():
"""Test that the slug is correctly generated when saving a Category."""
- category = Category(name="Test Category")
+ category = Category(title="Test Category")
category.save()
assert category.slug == slugify("Test Category")
@@ -26,10 +26,10 @@ def test_category_save_slug_generation():
@pytest.mark.django_db
def test_category_save_slug_uniqueness():
"""Test that an error is raised when trying to save a Category with a duplicate slug."""
- category1 = Category(name="Test Category")
+ category1 = Category(title="Test Category")
category1.save()
- category2 = Category(name="Test Category")
+ category2 = Category(title="Test Category")
with pytest.raises(ValueError) as excinfo:
category2.save()
@@ -43,48 +43,48 @@ def test_category_save_slug_uniqueness():
@pytest.mark.django_db
def test_category_save_invalid_name():
"""Test that an error is raised when trying to save a Category with an invalid name."""
- category = Category(name="-")
+ category = Category(title="-")
with pytest.raises(ValueError) as excinfo:
category.save()
- assert str(excinfo.value) == "Invalid name. Unable to generate a valid slug."
+ assert str(excinfo.value) == "Invalid title. Unable to generate a valid slug."
@pytest.mark.django_db
def test_category_slug_auto_generation():
# Test case 1: Slug auto-generated when not provided
- category1 = Category.objects.create(name="Test Category")
- assert category1.slug == slugify(category1.name)
+ category1 = Category.objects.create(title="Test Category")
+ assert category1.slug == slugify(category1.title)
# Test case 2: Slug not overridden when provided
- category2 = Category.objects.create(name="Another Category", slug="custom-slug")
+ category2 = Category.objects.create(title="Another Category", slug="custom-slug")
assert category2.slug == "custom-slug"
# Test case 3: Slug auto-generated with special characters
- category3 = Category.objects.create(name="Special !@#$%^&*() Category")
+ category3 = Category.objects.create(title="Special !@#$%^&*() Category")
assert category3.slug == "special-category"
# Test case 4: Slug auto-generated with non-ASCII characters
- category4 = Category.objects.create(name="Non-ASCII áéíóú Category")
+ category4 = Category.objects.create(title="Non-ASCII áéíóú Category")
assert category4.slug == "non-ascii-aeiou-category"
# Test case 5: Slug auto-generated with leading/trailing hyphens
- category5 = Category.objects.create(name="--Leading/Trailing Hyphens--")
+ category5 = Category.objects.create(title="--Leading/Trailing Hyphens--")
assert category5.slug == "leadingtrailing-hyphens"
- # Test case 6: Raise ValueError for invalid name
+ # Test case 6: Raise ValueError for invalid title
with pytest.raises(ValueError) as exc_info:
- Category.objects.create(name="!@#$%^&*()")
- assert str(exc_info.value) == "Invalid name. Unable to generate a valid slug."
+ Category.objects.create(title="!@#$%^&*()")
+ assert str(exc_info.value) == "Invalid title. Unable to generate a valid slug."
@pytest.mark.django_db
def test_get_categories_cache_enabled():
"""Test that the get_categories method returns the correct categories."""
- category1 = Category.objects.create(name="Category 1")
- category2 = Category.objects.create(name="Category 2")
- category3 = Category.objects.create(name="Category 3")
+ category1 = Category.objects.create(title="Category 1")
+ category2 = Category.objects.create(title="Category 2")
+ category3 = Category.objects.create(title="Category 3")
# Confirm the settings in settings_testing.py
assert settings.CACHE_CATEGORIES is True
@@ -97,9 +97,9 @@ def test_get_categories_cache_enabled():
@pytest.mark.django_db
def test_get_categories_cache_disabled():
"""Test that the get_categories method returns the correct categories."""
- category1 = Category.objects.create(name="Category 1")
- category2 = Category.objects.create(name="Category 2")
- category3 = Category.objects.create(name="Category 3")
+ category1 = Category.objects.create(title="Category 1")
+ category2 = Category.objects.create(title="Category 2")
+ category3 = Category.objects.create(title="Category 3")
# Confirm the settings in settings_testing.py
assert settings.CACHE_CATEGORIES is True
@@ -120,8 +120,8 @@ def test_get_category_by_slug_cache_enabled():
# Confirm the settings in settings_testing.py
assert settings.CACHE_CATEGORIES is True
- category1 = Category.objects.create(name="Category 1", slug="category-1")
- category2 = Category.objects.create(name="Category 2", slug="category-2")
+ category1 = Category.objects.create(title="Category 1", slug="category-1")
+ category2 = Category.objects.create(title="Category 2", slug="category-2")
category = Category.objects.get_category_by_slug("category-1")
@@ -138,8 +138,8 @@ def test_get_category_by_slug_cache_disabled():
settings.set("CACHE_CATEGORIES", False)
assert settings.CACHE_CATEGORIES is False
- category1 = Category.objects.create(name="Category 1", slug="category-1")
- category2 = Category.objects.create(name="Category 2", slug="category-2")
+ category1 = Category.objects.create(title="Category 1", slug="category-1")
+ category2 = Category.objects.create(title="Category 2", slug="category-2")
category = Category.objects.get_category_by_slug("category-1")
@@ -175,7 +175,7 @@ def test_category_permalink():
assert settings.CATEGORY_PATH_ENABLED is True
assert settings.CATEGORY_PATH == "test-url-category"
- category = Category.objects.create(name="Test Category", slug="test-category")
+ category = Category.objects.create(title="Test Category", slug="test-category")
assert category.permalink == "test-url-category/test-category"
diff --git a/tests/test_models_post.py b/tests/test_models_post.py
index e776526..fa0e2bb 100644
--- a/tests/test_models_post.py
+++ b/tests/test_models_post.py
@@ -15,12 +15,12 @@ def user():
@pytest.fixture
def category1():
- return Category.objects.create(name="Test Category1", slug="test-category1")
+ return Category.objects.create(title="Test Category1", slug="test-category1")
@pytest.fixture
def category2():
- return Category.objects.create(name="Test Category2", slug="test-category2")
+ return Category.objects.create(title="Test Category2", slug="test-category2")
@pytest.fixture
@@ -165,7 +165,7 @@ def test_get_published_post_by_slug_with_future_date(user):
@pytest.mark.django_db
def test_get_published_content_by_category_with_future_date(user):
- category = Category.objects.create(name="Test Category", slug="test-category")
+ category = Category.objects.create(title="Test Category", slug="test-category")
Post.post_objects.create(
title="Past Post",
slug="past-post",
diff --git a/tests/test_templatetags_djpress_tags.py b/tests/test_templatetags_djpress_tags.py
index b99793a..ef44e1f 100644
--- a/tests/test_templatetags_djpress_tags.py
+++ b/tests/test_templatetags_djpress_tags.py
@@ -30,7 +30,7 @@ def user():
@pytest.fixture
def category1():
category = Category.objects.create(
- name="General",
+ title="General",
slug="general",
)
return category
@@ -39,7 +39,7 @@ def category1():
@pytest.fixture
def category2():
category = Category.objects.create(
- name="News",
+ title="News",
slug="news",
)
return category
@@ -48,7 +48,7 @@ def category2():
@pytest.fixture
def category3():
category = Category.objects.create(
- name="Development",
+ title="Development",
slug="dev",
)
return category
@@ -167,7 +167,7 @@ def test_blog_title():
@pytest.mark.django_db
def test_get_categories(category1, category2, category3):
- categories = Category.objects.all()
+ categories = Category.objects.all().order_by("menu_order").order_by("title")
djpress_categories = djpress_tags.get_categories()
assert category1 in categories
@@ -342,7 +342,7 @@ def test_post_category_link_without_category_path(category1):
settings.set("CATEGORY_PATH_ENABLED", False)
assert settings.CATEGORY_PATH_ENABLED is False
- assert djpress_tags.post_category_link(category1) == category1.name
+ assert djpress_tags.post_category_link(category1) == category1.title
# Set back to defaults
settings.set("CATEGORY_PATH_ENABLED", True)
@@ -360,7 +360,7 @@ def test_post_category_link_without_category_pathwith_one_link(category1):
settings.set("CATEGORY_PATH_ENABLED", False)
assert settings.CATEGORY_PATH_ENABLED is False
- assert djpress_tags.post_category_link(category1, "class1") == category1.name
+ assert djpress_tags.post_category_link(category1, "class1") == category1.title
# Set back to defaults
settings.set("CATEGORY_PATH_ENABLED", True)
@@ -372,7 +372,7 @@ def test_post_category_link_with_category_path(category1):
assert settings.CATEGORY_PATH_ENABLED is True
assert settings.CATEGORY_PATH == "test-url-category"
- expected_output = f'{category1.name}'
+ expected_output = f'{category1.title}'
assert djpress_tags.post_category_link(category1) == expected_output
@@ -383,7 +383,7 @@ def test_post_category_link_with_category_path_with_one_link_class(category1):
assert settings.CATEGORY_PATH_ENABLED is True
assert settings.CATEGORY_PATH == "test-url-category"
- expected_output = f'{category1.name}'
+ expected_output = f'{category1.title}'
assert djpress_tags.post_category_link(category1, "class1") == expected_output
@@ -394,7 +394,7 @@ def test_post_category_link_with_category_path_with_two_link_classes(category1):
assert settings.CATEGORY_PATH_ENABLED is True
assert settings.CATEGORY_PATH == "test-url-category"
- expected_output = f'{category1.name}'
+ expected_output = f'{category1.title}'
assert (
djpress_tags.post_category_link(category1, "class1 class2") == expected_output
@@ -609,20 +609,20 @@ def test_author_name_no_author():
@pytest.mark.django_db
-def test_category_name(category1):
- """category_name only works if there's a category in the context."""
+def test_category_title(category1):
+ """category_title only works if there's a category in the context."""
context = Context({"category": category1})
# Test case 1 - no options
- expected_output = category1.name
- assert djpress_tags.category_name(context) == expected_output
+ expected_output = category1.title
+ assert djpress_tags.category_title(context) == expected_output
# Test case 2 - with options
expected_output = (
- f'View posts in the {category1.name} category
'
+ f'View posts in the {category1.title} category
'
)
assert (
- djpress_tags.category_name(
+ djpress_tags.category_title(
context,
outer="h1",
outer_class="title",
@@ -633,12 +633,12 @@ def test_category_name(category1):
)
-def test_category_name_no_category():
+def test_category_title_no_category():
"""If there's no category in the context, return an empty string."""
context = Context({"foo": "bar"})
- assert djpress_tags.category_name(context) == ""
- assert type(djpress_tags.category_name(context)) == str
+ assert djpress_tags.category_title(context) == ""
+ assert type(djpress_tags.category_title(context)) == str
@pytest.mark.django_db
@@ -857,7 +857,7 @@ def test_blog_pages(test_page1, test_page2):
def test_blog_page_title(test_post1, test_page1):
# Test case 1 - category page
context = Context({"category": test_post1.categories.first()})
- assert test_post1.categories.first().name == djpress_tags.blog_page_title(context)
+ assert test_post1.categories.first().title == djpress_tags.blog_page_title(context)
# Test case 2 - author page
context = Context({"author": test_post1.author})
diff --git a/tests/test_templatetags_helpers.py b/tests/test_templatetags_helpers.py
index 88478f5..51e39b3 100644
--- a/tests/test_templatetags_helpers.py
+++ b/tests/test_templatetags_helpers.py
@@ -25,7 +25,7 @@ def user():
@pytest.fixture
def category1():
category = Category.objects.create(
- name="General",
+ title="General",
slug="general",
)
return category
@@ -34,7 +34,7 @@ def category1():
@pytest.fixture
def category2():
category = Category.objects.create(
- name="News",
+ title="News",
slug="news",
)
return category
@@ -43,7 +43,7 @@ def category2():
@pytest.fixture
def category3():
category = Category.objects.create(
- name="Development",
+ title="Development",
slug="dev",
)
return category
@@ -76,9 +76,9 @@ def test_categories_html(category1, category2, category3):
link_class = "category"
expected_output = (
'"
)
assert (
@@ -94,9 +94,9 @@ def test_categories_html(category1, category2, category3):
link_class = ""
expected_output = (
""
)
assert (
@@ -112,9 +112,9 @@ def test_categories_html(category1, category2, category3):
link_class = "category"
expected_output = (
'"
)
assert (
@@ -130,9 +130,9 @@ def test_categories_html(category1, category2, category3):
link_class = ""
expected_output = (
""
)
assert (
@@ -148,9 +148,9 @@ def test_categories_html(category1, category2, category3):
link_class = "category"
expected_output = (
''
- f'{category1.name}, '
- f'{category2.name}, '
- f'{category3.name}'
+ f'{category1.title}, '
+ f'{category2.title}, '
+ f'{category3.title}'
""
)
assert (
@@ -166,9 +166,9 @@ def test_categories_html(category1, category2, category3):
link_class = ""
expected_output = (
""
- f'{category1.name}, '
- f'{category2.name}, '
- f'{category3.name}'
+ f'{category1.title}, '
+ f'{category2.title}, '
+ f'{category3.title}'
""
)
assert (
@@ -185,12 +185,12 @@ def testcategory_link(category1):
# Test case 1 - no link class
link_class = ""
- expected_output = f'{category1.name}'
+ expected_output = f'{category1.title}'
assert category_link(category1, link_class) == expected_output
# Test case 2 - with link class
link_class = "category-class"
- expected_output = f'{category1.name}'
+ expected_output = f'{category1.title}'
assert category_link(category1, link_class) == expected_output
diff --git a/tests/test_views.py b/tests/test_views.py
index af334c7..2259725 100644
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -23,7 +23,7 @@ def user():
@pytest.fixture
def category():
category = Category.objects.create(
- name="Test Category",
+ title="Test Category",
slug="test-category",
)
return category