Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

fsbraun
Copy link
Member

@fsbraun fsbraun commented Sep 10, 2025

  • fix: copy lang management command

Include copy of related PageUrl models

  • Update cms/management/commands/subcommands/copy.py

  • Apply suggestions from code review

  • Update cms/management/commands/subcommands/copy.py

  • Add test to check page urls are created

  • Add import for sys module in test_management.py


Description

Related resources

Checklist

Summary by Sourcery

Extend the copy language management command to duplicate related PageUrl models, including slug and path generation, and ensure proper parent-child ordering.

Enhancements:

  • Include copying of PageUrl instances when duplicating page languages and generate unique slugs and paths.
  • Order pages by tree path so parent pages are created before children during copy.
  • Update page.language list to include the target language before copying URLs.

Tests:

  • Add test to verify that PageUrl records are created for the new language with the correct count.

* fix: copy lang management command

Include copy of related PageUrl models

* Update cms/management/commands/subcommands/copy.py

* Apply suggestions from code review

* Update cms/management/commands/subcommands/copy.py

* Add test to check page urls are created

* Add import for sys module in test_management.py

---------

Co-authored-by: Fabian Braun <[email protected]>
Copy link
Contributor

sourcery-ai bot commented Sep 10, 2025

Reviewer's Guide

Extends the copy language management command to include PageUrl instances by importing necessary models/utilities, enforcing tree order, generating new slugs/paths, and adds tests to verify URL duplication.

Sequence diagram for copying PageUrl in the copy language management command

sequenceDiagram
    participant "Management Command"
    participant "Page"
    participant "PageUrl"
    participant "PageContent"
    participant "User"
    participant "Site"
    participant "ParentPage"

    "Management Command"->>"Site": Get site
    "Management Command"->>"Page": Iterate pages in tree order
    "Management Command"->>"Page": Check if from_lang exists
    alt If from_lang exists
        "Management Command"->>"PageContent": Create new PageContent for to_lang
        "Management Command"->>"Page": Update languages to include to_lang
        "Management Command"->>"PageUrl": Get PageUrl for from_lang
        "Management Command"->>"ParentPage": Get parent page (if any)
        "Management Command"->>"PageUrl": Generate new slug and path for to_lang
        "Management Command"->>"PageUrl": Create new PageUrl for to_lang
    end
Loading

Entity relationship diagram for Page and PageUrl after copy command update

erDiagram
    Page ||--o{ PageUrl : has
    Page {
        id int PK
        parent_id int FK
        path string
        languages list
    }
    PageUrl {
        id int PK
        page_id int FK
        language string
        slug string
        path string
    }
Loading

Class diagram for updated Page and PageUrl handling in copy command

classDiagram
    class Page {
        +get_languages()
        +update_languages(langs)
        +get_path(lang)
        parent : Page
        path : str
    }
    class PageUrl {
        language : str
        slug : str
        path : str
    }
    class PageContent {
        +create(**kwargs)
    }
    class User {
    }
    Page "1" -- "*" PageUrl : has
    Page "1" -- "*" PageContent : has
    Page "1" -- "0..1" Page : parent
    PageUrl "*" -- "1" User : created_by
    PageContent "*" -- "1" User : created_by
Loading

File-Level Changes

Change Details Files
Include PageUrl model and enforce node path order in the copy command
  • Imported PageUrl into copy command
  • Imported get_available_slug to compute new slugs
  • Changed Page queryset to order_by('path') for correct parent-first processing
cms/management/commands/subcommands/copy.py
Implement PageUrl duplication logic
  • Retrieve source PageUrl and convert to dict without PK
  • Determine parent path and compute available slug
  • Build new path and create new PageUrl with with_user
cms/management/commands/subcommands/copy.py
Add tests to verify PageUrl copying
  • Capture initial PageUrl count in source language
  • Assert that copied PageUrl count matches original for target language
cms/tests/test_management.py

Possibly linked issues

  • #0: The PR fixes the cms copy lang command by adding logic to correctly copy associated PageUrl models, which directly resolves the DoesNotExist errors reported in the issue.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

👋 Hi there!

Please remember to MERGE COMMIT pull requests from main!

Do not SQUASH commits to preserve history for the changelog.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Instead of ordering pages by path to enforce parent-first order, use the model’s MPTT attributes (e.g. tree_id and lft) for deterministic tree traversal.
  • Extract the PageUrl copy logic into a shared helper or into the Page model’s copy method to avoid duplication and improve maintainability.
  • Iterate over all related PageUrl instances (page.urls.all()) so that any URL aliases are also copied, not just the primary URL.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Instead of ordering pages by `path` to enforce parent-first order, use the model’s MPTT attributes (e.g. `tree_id` and `lft`) for deterministic tree traversal.
- Extract the PageUrl copy logic into a shared helper or into the Page model’s copy method to avoid duplication and improve maintainability.
- Iterate over all related PageUrl instances (`page.urls.all()`) so that any URL aliases are also copied, not just the primary URL.

## Individual Comments

### Comment 1
<location> `cms/management/commands/subcommands/copy.py:98` </location>
<code_context>
+                        page.update_languages(page.get_languages() + [to_lang])
+
+                    # copy PageUrls - inspired from pagemodels.Page.copy() - possibly refactorable
+                    page_url = page.urls.get(language=from_lang)
+                    parent_page = page.parent
+
+                    new_url = model_to_dict(page_url)
</code_context>

<issue_to_address>
No error handling for missing PageUrl in source language.

Accessing page.urls.get(language=from_lang) without checking for existence can cause exceptions. Please add error handling to manage missing PageUrl cases.
</issue_to_address>

### Comment 2
<location> `cms/management/commands/subcommands/copy.py:114` </location>
<code_context>
+                        path = page_url.slug
+
+                    new_url["slug"] = get_available_slug(site, path, to_lang)
+                    new_url["path"] = '%s/%s' % (base, new_url["slug"]) if base else new_url["slug"]
+                    PageUrl.objects.with_user(user).create(**new_url)
+
</code_context>

<issue_to_address>
Path construction may not handle leading/trailing slashes or empty base correctly.

Normalize base and slug to prevent double slashes or malformed paths when concatenating.

Suggested implementation:

```python
                        base = parent_page.get_path(to_lang)
                        # Normalize base and slug to avoid double slashes
                        base_norm = base.strip('/') if base else ''
                        slug_norm = page_url.slug.strip('/')
                        path = '%s/%s' % (base_norm, slug_norm) if base_norm else slug_norm
                    else:
                        base_norm = ''
                        slug_norm = page_url.slug.strip('/')
                        path = slug_norm

                    new_url["slug"] = get_available_slug(site, path, to_lang)

```

```python
                    new_url["slug"] = get_available_slug(site, path, to_lang)
                    # Normalize base and slug for the final path as well
                    final_base = base.strip('/') if base else ''
                    final_slug = new_url["slug"].strip('/')
                    new_url["path"] = '%s/%s' % (final_base, final_slug) if final_base else final_slug
                    PageUrl.objects.with_user(user).create(**new_url)

```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +98 to +99
page_url = page.urls.get(language=from_lang)
parent_page = page.parent
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: No error handling for missing PageUrl in source language.

Accessing page.urls.get(language=from_lang) without checking for existence can cause exceptions. Please add error handling to manage missing PageUrl cases.

@fsbraun fsbraun merged commit d568e81 into release/5.0.x Sep 10, 2025
70 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants