question regarding url dispatch with very similar routes

11 views
Skip to first unread message

Jonathan Vanasco

unread,
Dec 18, 2019, 8:39:55 PM12/18/19
to pylons-discuss
I hope someone here can suggest a good way of handling this situation.

We have an application that supports a given user profile view via two or more possible URL patterns:

   "/users/{username_regex}"
   "/users/{userid_regex}"

To handle this within one route declaration, a `factory` is used:

        config.add_route("user_focus", "/users/{user_identifier}", factory=factory__useraccount)

The factory does regex on the `user_identifier` placeholder, and updates the request matchdict with an extracted `user_name` or `user_id`. this works perfect and allows us to avoid this:

        config.add_route("user_focus_a", "/users/{username_identifier}")
        config.add_route("user_focus_b", "/users/{userid_identifier}")

we also avoid using view_config to register 2 routes onto each callable


We've added some new functionality, and I'm having a problem figuring out the best way to implement it.

users matching a particular new format of the `user_identifier` placeholder need to respond to another route

there are essentially 4 potential patterns

        config.add_route("usertype_a_focus_username", "/users/{username_A_regex}")
        config.add_route("usertype_a_focus_userid", "/users/{userid_A_regex}")
        config.add_route("usertype_b_focus_username", "/users/{username_B_regex}")
        config.add_route("usertype_b_focus_userid", "/users/{userid_B_regex}")

ideally i'd love to simplify this into 2 routes, as they map to 2 views. something like:

        config.add_route("usertype_a_focus", "/users/{usertype_a_identifier}", ...)
        config.add_route("usertype_b_focus", "/users/{usertype_b_identifier}", ...)

the problem with the approach is that `usertype_a_focus` grabs the route,  and the `factory` (to my knowledge) can only raise a not-found - not fail the lookup and continue on to future patterns - so `usertype_b_focus` never runs.

it looks like I could do this by running a regex in the placeholder, but then I'm running it again in the factory to alter the matchdict. that will also require duplicating an already complied regex into the pattern syntax for the route.  the app is large, so I'd like to avoid having to keep two different regex patterns in sync with one another.

does anyone know if it is possible to better use factory, or implement some other amazing Pyramid utility like predicates or something else in this situation?

thank you all in advance.

Michael Merickel

unread,
Dec 19, 2019, 12:26:34 PM12/19/19
to Pylons
You didn't make it completely clear what you're doing with your view_config but I assume it's something to do with the match_param predicate after your factory updates the matchdict. That's fine, and you could use it to annotate the request with another attribute and then write a custom predicate for your views to use instead of the match_param. Think something like request.user_focus = 'a_username', and @view_config(route_name='user_focus', user_type='a_username') which will work well if they are mutually exclusive.

--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/d603ef95-b391-43e2-8c2f-82132fc1f952%40googlegroups.com.


--

Michael

Jonathan Vanasco

unread,
Dec 19, 2019, 3:53:20 PM12/19/19
to pylons-discuss


On Thursday, December 19, 2019 at 12:26:34 PM UTC-5, Michael Merickel wrote:
You didn't make it completely clear what you're doing with your view_config but I assume it's something to do with the match_param predicate after your factory updates the matchdict. That's fine, and you could use it to annotate the request with another attribute and then write a custom predicate for your views to use instead of the match_param. Think something like request.user_focus = 'a_username', and @view_config(route_name='user_focus', user_type='a_username') which will work well if they are mutually exclusive.

Thanks, Michael.  I'm not doing that, but it looks like i should!

Your reply gave me enough insight/hints to get something working, and I'm pretty happy with it from a maintainability standpoint.

I'm now doing the following:



def factory__user_type_discriminator(request):
    """inspects the matchdict's 'integrated_user_identifier' placeholder;
       sets 'user_type=A' or 'user_type=B' in the matchdict
    """
    pass

config.add_route("integrated_user_focus",
                 "/users/{integrated_user_identifier}",
                 factory=factory__user_type_discriminator
                 )


class ViewClass(handler):

   
@view_config(route_name="integrated_user_focus", match_param='user_type=A')
     
def view_type_a(self, request):
       
pass
 
   
@view_config(route_name="integrated_user_focus", match_param='user_type=B')
     
def view_type_b(self, request):
        pass







Reply all
Reply to author
Forward
0 new messages