Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve request kwargs while defining MenuItem #70

Closed
jokiefer opened this issue Feb 11, 2021 · 4 comments
Closed

Resolve request kwargs while defining MenuItem #70

jokiefer opened this issue Feb 11, 2021 · 4 comments
Labels
enhancement Something can be improved

Comments

@jokiefer
Copy link

related to #19

I struggled also about the issue to catch the current pk attribute from the current request and pass it into the menu.

I've got the following urls.py for example:

app_name = 'structure'
urlpatterns = [
   ...
    path('groups', MrMapGroupTableView.as_view(), name='group_overview'),
    path('groups/new', NewMrMapGroup.as_view(), name='group_new'),
    path('groups/<pk>', MrMapGroupDetailView.as_view(), name='group_details'),
    path('groups/<pk>/members', MrMapGroupMembersTableView.as_view(), name='group_members'),
    path('groups/<pk>/edit', EditGroupView.as_view(), name='group_edit'),
   ...
]

How can i resolve the current requested pk from the request kwargs for example in the menus.py:

# Define children for the group menu
group_details_children = (
    MenuItem("Edit Group",
             reverse('structure:group_edit', args=pk), # pk not resolved here for now
             weight=10,
             icon="user"),
    MenuItem(_("Members"),
             reverse('structure:group_members', args=pk), # pk not resolved here for now
             weight=20,
    MenuItem(_("Publishers"),
             reverse('structure:group_publishers', args=pk), # pk not resolved here for now
             weight=30,
)

# Add a My Account item to our user menu
Menu.add_item("group_details", MenuItem(_("Details"),
                                        reverse('structure:group_details', args=pk), # pk not resolved here for now
                                        weight=10,
                                        children=group_details_children))
@jokiefer
Copy link
Author

jokiefer commented Feb 11, 2021

I've made it by customizing the MenuItem class as shown in the code snippet below.

from django.http import HttpRequest
from django.urls import reverse
from menu import MenuItem, Menu
from django.utils.translation import gettext as _


def resolve_url(request: HttpRequest, view_name: str):
    return reverse(view_name, args=[request.resolver_match.kwargs.get('pk'), ])


class CustomMenuItem(MenuItem):

    def process(self, request):
        # evaluate our url
        if callable(self.url):
            self.url = self.url(request, self.view_name)
        super().process(request)


children = (
    CustomMenuItem(_("Edit Group"),
                   resolve_url,
                   weight=10,
                   view_name='structure:group_edit'),
    CustomMenuItem(_("Delete Group"),
                   resolve_url,
                   weight=20,
                   view_name='structure:group_remove',),
    CustomMenuItem(_("Members"),
                   resolve_url,
                   weight=30,
                   view_name='structure:group_members',),
    CustomMenuItem(_("Publishes for"),
                   resolve_url,
                   weight=40,
                   view_name='structure:group_publisher_overview'),
)

Menu.add_item('group_details', CustomMenuItem(_("Details"),
                                              resolve_url,
                                              weight=10,
                                              children=children,
                                              view_name='structure:group_details'))

I'm wondering about that this isn't already implemented. Maybe a PR with the enhancement of a simple check if self.url callable would be enough to add this feature by default. Or do i misunderstood the documentation somewhere?

@timnyborg
Copy link
Contributor

I tried to do something similar, and ran into the same issue that url won't accept a callable (but really should). However, children can accept a callable which takes request, so you can just replace the tuple with a function:

def children(request):
    pk = request.resolver_match.kwargs.get('pk')
    return [
        CustomMenuItem(_("Edit Group"),
                   reverse('structure:group_edit', args=[pk]),
                   weight=10,
                   view_name='structure:group_edit'),
    ...
    ]

I think your custom class is required for callable URLs at the top of the hierarchy, though.

@jokiefer
Copy link
Author

@timnyborg

Nice. Pretty good solution to define the children's, cause you could also drop the subclass CustomMenuItem.

I think your custom class is required for callable URLs at the top of the hierarchy, though.

Yep - Cause there is no callable check. If so, we could adapt your solution again, without defining the view_name attr.

@timnyborg
Copy link
Contributor

timnyborg commented Feb 13, 2021

@jokiefer
I've adapted your code into pull request #71, which works on parent and child nodes alike.

@kytta kytta added the enhancement Something can be improved label May 8, 2022
@kytta kytta mentioned this issue May 8, 2022
@kytta kytta added this to the v2.0.0 milestone May 9, 2022
@kytta kytta closed this as completed in 72e930f Nov 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Something can be improved
Projects
None yet
Development

No branches or pull requests

3 participants