22
33from  django .conf .urls  import  include , url 
44
5- from  rest_framework .compat  import  URLResolver , get_regex_pattern 
5+ from  rest_framework .compat  import  (
6+     URLResolver , get_regex_pattern , is_route_pattern , path , register_converter 
7+ )
68from  rest_framework .settings  import  api_settings 
79
810
9- def  apply_suffix_patterns (urlpatterns , suffix_pattern , suffix_required ):
11+ def  _get_format_path_converter (suffix_kwarg , allowed ):
12+     if  allowed :
13+         if  len (allowed ) ==  1 :
14+             allowed_pattern  =  allowed [0 ]
15+         else :
16+             allowed_pattern  =  '(?:%s)'  %  '|' .join (allowed )
17+         suffix_pattern  =  r"\.%s/?"  %  allowed_pattern 
18+     else :
19+         suffix_pattern  =  r"\.[a-z0-9]+/?" 
20+ 
21+     class  FormatSuffixConverter :
22+         regex  =  suffix_pattern 
23+ 
24+         def  to_python (self , value ):
25+             return  value .strip ('./' )
26+ 
27+         def  to_url (self , value ):
28+             return  '.'  +  value  +  '/' 
29+ 
30+     converter_name  =  'drf_format_suffix' 
31+     if  allowed :
32+         converter_name  +=  '_'  +  '_' .join (allowed )
33+ 
34+     return  converter_name , FormatSuffixConverter 
35+ 
36+ 
37+ def  apply_suffix_patterns (urlpatterns , suffix_pattern , suffix_required , suffix_route = None ):
1038    ret  =  []
1139    for  urlpattern  in  urlpatterns :
1240        if  isinstance (urlpattern , URLResolver ):
@@ -18,8 +46,18 @@ def apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required):
1846            # Add in the included patterns, after applying the suffixes 
1947            patterns  =  apply_suffix_patterns (urlpattern .url_patterns ,
2048                                             suffix_pattern ,
21-                                              suffix_required )
22-             ret .append (url (regex , include ((patterns , app_name ), namespace ), kwargs ))
49+                                              suffix_required ,
50+                                              suffix_route )
51+ 
52+             # if the original pattern was a RoutePattern we need to preserve it 
53+             if  is_route_pattern (urlpattern ):
54+                 assert  path  is  not None 
55+                 route  =  str (urlpattern .pattern )
56+                 new_pattern  =  path (route , include ((patterns , app_name ), namespace ), kwargs )
57+             else :
58+                 new_pattern  =  url (regex , include ((patterns , app_name ), namespace ), kwargs )
59+ 
60+             ret .append (new_pattern )
2361        else :
2462            # Regular URL pattern 
2563            regex  =  get_regex_pattern (urlpattern ).rstrip ('$' ).rstrip ('/' ) +  suffix_pattern 
@@ -29,7 +67,17 @@ def apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required):
2967            # Add in both the existing and the new urlpattern 
3068            if  not  suffix_required :
3169                ret .append (urlpattern )
32-             ret .append (url (regex , view , kwargs , name ))
70+ 
71+             # if the original pattern was a RoutePattern we need to preserve it 
72+             if  is_route_pattern (urlpattern ):
73+                 assert  path  is  not None 
74+                 assert  suffix_route  is  not None 
75+                 route  =  str (urlpattern .pattern ).rstrip ('$' ).rstrip ('/' ) +  suffix_route 
76+                 new_pattern  =  path (route , view , kwargs , name )
77+             else :
78+                 new_pattern  =  url (regex , view , kwargs , name )
79+ 
80+             ret .append (new_pattern )
3381
3482    return  ret 
3583
@@ -60,4 +108,12 @@ def format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None):
60108    else :
61109        suffix_pattern  =  r'\.(?P<%s>[a-z0-9]+)/?$'  %  suffix_kwarg 
62110
63-     return  apply_suffix_patterns (urlpatterns , suffix_pattern , suffix_required )
111+     if  path  and  register_converter :
112+         converter_name , suffix_converter  =  _get_format_path_converter (suffix_kwarg , allowed )
113+         register_converter (suffix_converter , converter_name )
114+ 
115+         suffix_route  =  '<%s:%s>'  %  (converter_name , suffix_kwarg )
116+     else :
117+         suffix_route  =  None 
118+ 
119+     return  apply_suffix_patterns (urlpatterns , suffix_pattern , suffix_required , suffix_route )
0 commit comments