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 = ( '
' - f'{category1.name}, ' - f'{category2.name}, ' - f'{category3.name}' + f'{category1.title}, ' + f'{category2.title}, ' + f'{category3.title}' "
" ) assert ( @@ -130,9 +130,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 ( @@ -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