Skip to content

Add SimplePathRouter #6789

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

Merged
merged 6 commits into from
Jan 12, 2023
Merged

Add SimplePathRouter #6789

merged 6 commits into from
Jan 12, 2023

Conversation

sevdog
Copy link
Contributor

@sevdog sevdog commented Jul 6, 2019

Description

Add SimplePathRouter to handle Django 2.x path converters (refs #6148).

@tomchristie tomchristie added this to the 3.10 Release milestone Jul 8, 2019
@tomchristie
Copy link
Member

Milestoning for review. Thanks!

@sevdog
Copy link
Contributor Author

sevdog commented Jul 8, 2019

It may be improved a bit if support for Django 1.x gets dropped (ie: some bad if will be removed).

@rpkilby
Copy link
Member

rpkilby commented Jul 8, 2019

I'm thinking this should be pushed to the 3.11 release, as that is when we'll likely drop Django 1.11

@tomchristie tomchristie modified the milestones: 3.10 Release, 3.11 Release Jul 9, 2019
@tomchristie
Copy link
Member

@rpkilby Good call

@sevdog
Copy link
Contributor Author

sevdog commented Jul 13, 2019

@rpkilby I have updated with CRUD tests and removed Django 1.11 compact. Tell me if everything is fine for you.

Copy link
Member

@auvipy auvipy left a comment

Choose a reason for hiding this comment

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

can you skip tests for Django 1.11 for this PR? dj1.11 seems to be supported for some more time.

@sevdog
Copy link
Contributor Author

sevdog commented Nov 21, 2019

can you skip tests for Django 1.11 for this PR? dj1.11 seems to be supported for some more time.

I have also added an assertion in SimplePathRouter.get_urls to raise an assertion error if path is not defined.

@sevdog
Copy link
Contributor Author

sevdog commented Nov 22, 2019

Ok... seems that pytest.mark.skipif has not worked as expected. I will recheck it as soon as I can.

Copy link
Member

@auvipy auvipy left a comment

Choose a reason for hiding this comment

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

can you rebase plz?

@sevdog sevdog force-pushed the path-router branch 2 times, most recently from 17af0e1 to c1348cf Compare December 5, 2019 20:05
@sevdog
Copy link
Contributor Author

sevdog commented Dec 5, 2019

Rebased.

@tomchristie
Copy link
Member

We've not dropped 1.11 on this pass, since its LTS.

Wondering if we might just outright switch the behavior on the next release - I'd rather we didn't have two different have two different class implementations here.

@sevdog
Copy link
Contributor Author

sevdog commented Dec 12, 2019

@tomchristie you are right that a single-class implementation would be better.

I think that it can be done since the difference between those two are just two methods (get_urls and get_get_lookup_*). Those methods could be guided with some initialization param in class constructor.

I will try to refactor the code to have a single class.

@tomchristie
Copy link
Member

When we drop 1.11 I'd actually probably be okay with us just completely switching to .path, so long as there's some kind of way for users to stick with the older behavior.

There's not really any great options for us here.

@sevdog sevdog force-pushed the path-router branch 2 times, most recently from b1d231f to 4696b19 Compare December 12, 2019 19:42
@stale stale bot removed the stale label Oct 16, 2022
@sevdog
Copy link
Contributor Author

sevdog commented Oct 18, 2022

@auvipy I have rebased the branch with current master. Let me know if any other change is needed.

@auvipy
Copy link
Member

auvipy commented Oct 18, 2022

the workflow need to be triggered

@camuthig
Copy link

I am playing around with this PR a bit, and in my case the major reason I am trying to move to path over regular expressions is to get custom converter behaviors for the URL arguments. I have a function that transforms my model IDs as they come into and out of the API layer, and I have implemented this as a custom converter to do something like <encoded:pk> instead of <int:pk> to automatically decode the IDs before they reach any of my code.

I am able to make this work with the code in this PR by setting lookup_value_regex = "encoded" on my views. However, since I am not defining a regex here, the usage feels a little unnatural. The same behavior would apply to standard converters, like uuid.

This isn't a blocker, since it seems to be working just fine, but figured it was worth bringing up while it is still in PR. If there is an alternative way to approach these custom converters, let me know, and I will give that a try too.

@sevdog
Copy link
Contributor Author

sevdog commented Oct 28, 2022

@camuthig you pointed out an interesting use case. I could change the code to use an "alternative" attribute with a more readable name to solve it, but this feels quite a mock-fix IMO.

Preserve backwards compatibility and handle this use case in an elegant way is a bit hard.

I would like to go back to my first implementation where there were 2 base router classes: one for regex and one for path, so there is no chance of mixing code and name would be quite expressive (but the project owner clearly expressed he prefers to have a single class).

The other way I see is to rework the current implementation in order to handle the choice between regex or path on a per view basis and not globally on the router, the problem here is to handle Route and DynamicRoute url attribute (which is currently a way orrible hack also in this implementation, since there is no guarantee that route url templates do not contains any other regex-language characters other than an initial ^ and a final $).

@tomchristie what do you think would fit better?

@auvipy
Copy link
Member

auvipy commented Nov 21, 2022

Let us focus on the actual issue first. we are going to make the SimplRouter allowing new path based routing. should we also do the same for the DefaultRouter?

@sevdog
Copy link
Contributor Author

sevdog commented Nov 21, 2022

@auvipy, do you mean this line?

root_url = re_path(r'^$', view, name=self.root_view_name)

Apart from that DefaultRouter should inherit from SimpleRouter

@auvipy
Copy link
Member

auvipy commented Nov 21, 2022

yeah, OK. I got commit access recently. so want to prioritize this one and draw a conclusion very soon to get this merged. of course considering all the natural edge cases are ironed out

notes_router = SimpleRouter()
notes_router.register(r'notes', NoteViewSet)

notes_path_router = SimpleRouter(use_regex_path=False)
Copy link
Member

Choose a reason for hiding this comment

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

can we add another test case which use DeafultRouter please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It should not be a problem to replicate that test also with the other router.

@sevdog
Copy link
Contributor Author

sevdog commented Nov 23, 2022

I have added a small change to address the semantic issue pointed by @camuthig.

@auvipy
Copy link
Member

auvipy commented Nov 23, 2022

that's great. do you see any other documentation changes needed for this?


class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_id'
lookup_value_regex = '[0-9a-f]{32}'

class MyPathModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_uuid'
lookup_value_converter = 'uuid'
Copy link
Member

Choose a reason for hiding this comment

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

can we use better name for lookup_value_converter?any better suited name instead of converter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used "converter" since django calls these elements path converters, maybe we can use the full expanded name to have lookup_value_pathconverter (or lookup_value_path_converter).

Any suggestion is welcome.

Copy link
Member

Choose a reason for hiding this comment

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

I would inclined to @tomchristie for a better insight here as I'm bit confused about naming

Copy link
Member

Choose a reason for hiding this comment

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

what about just lookup_value_path? this alighned with the name lookup_value_regex

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that it would be better to use the same naming of django.

In this case it was named "converter" thus an attribute which should define one should be named after that. In this way it is easier to find references to what this element does.

Copy link
Member

Choose a reason for hiding this comment

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

OK I am going to merge this, we can improve it if needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.