Django redirect preserving subpath - python

In my urls.py I have:
urlpatterns = [
url(r'^admin/', admin.site.urls, name='admin'),
url(r'^django-admin/', RedirectView.as_view(url='/admin/', permanent=True)),
]
So if I go to localhost:8000/django-admin/ it successfully redirects me to localhost:8000/admin/, and if I go to localhost:8000/django-admin/my-app/ it also redirects me to localhost:8000/admin/.
How could I make localhost:8000/django-admin/my-app/ go to localhost:8000/admin/my-app/? And the same for every possible subpath e.g. localhost:8000/django-admin/my-app/my-view, localhost:8000/django-admin/another-app/, etc?

According to the docs something like this should work, you can capture groups from the path and pass them to the url
The given URL may contain dictionary-style string formatting, which will be interpolated against the parameters captured in the URL. Because keyword interpolation is always done (even if no arguments are passed in), any "%" characters in the URL must be written as "%%" so that Python will convert them to a single percent sign on output.
url(r'^django-admin/(?P<rest>.*)', RedirectView.as_view(url='/admin/%(rest)s', permanent=True)
This website is particularly useful for figuring out how the built-in class-based views work http://ccbv.co.uk/projects/Django/2.2/django.views.generic.base/RedirectView/#get_redirect_url

Related

How does Django map the urls when there is ambiguity

I have the url patterns in my project urls.py
url(r'^', include('app.urls')),
url(r'^api/app/', include('app.url.router_urls')),
and in the app.urls i have something like
url(r'^api/app/user$', views.user_validator),
and in the app.url.router_urls i have something like
url('^v1/', include('app.url.app_v1.urls'))
I have a question around these.
so when the request is BASE_URL/api/app/{user} which url will be mapped to this?
and how about BASE_URL/api/app/v1/ which url will be mapped.
this will map first with ^ right and will use the app.urls for both?
thanks
Django will fire the first view for which the URL matches. It thus evaluates the urls top-to-bottom.
It will thus first look to the included app.urls and if that matches (if you visited hostname/api/app/user, it will "fire" that view.
Note that here your user is not a variable, this is simply the word user, so if you visit {user}, it will keep looking, but since none of the patterns "fire", it will thus return a 404.
You can work with URL parameters, with:
url(r'^api/app/(?P<user>[\w{}]+)$', views.user_validator),
If we do this however, it will also match with hostname/api/app/v1, since then it sees that [\w{}]+ matches with v1.
Therefore it is important to order the url patterns from more specific to less specific, or even better: design the URL patterns such that there is no overlap.
Note: As of django-3.1, url(…) [Django-doc] is
deprecated in favor of re_path(…) [Django-doc].
Furthermore a new syntax for paths has been introduced with path converters: you
use path(…) [Django-doc] for that.

Possible to escape or otherwise pass a value that includes / in Django URL

I'm building a tool using Django that works with the part numbers that my company uses, one set of part numbers includes /'s which I didn't realize when I set up the url to access the part summary.
Now when try to pass one of those part numbers it breaks things, is there a way to work around this? I'd like to avoid changing the part number or adding a unique id with no other meaning to the model.
an example part number that causes the problem is P-030-P-401/ND the url pattern is /parts/
Thanks in advance
If you are allowed to change the route a bit, this is an option with just a few characters difference:
www.domain.com/parts/?part_id=P-030-P-401/ND
Example setup:
urls.py
urlpatterns = [
# other paths here
path("parts/", view_test),
]
views.py
def view_test(request):
part_id = request.GET.get("part_id")
return render(request, "parts/test.html", {"part_id": part_id})
test.html
{{part_id}}
Depending on browser settings maybe replace / with %2F, but it's working with the slash for me on Firefox.

Pass a URL as parameter in Django Urls

I'm working on a Django(2) project in which I need to pass an URL as a parameter in a Django URL,
Here's what i have tried:
urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^api/(?P<address>.*)/$', PerformImgSegmentation.as_view()),
]
views.py:
class PerformImgSegmentation(generics.ListAPIView):
def get(self, request, *args, **kwargs):
img_url = self.kwargs.get('address')
print(img_url)
print('get request')
return 'Done'
But it doesn't work, I have passed an argument with the name as address via postman, but it failed.
It returns this error:
Not Found: /api/
[05/Sep/2018 15:28:06] "GET /api/ HTTP/1.1" 404 2085
Django 2.0 and later use now path func constructors to specify URLs. I'm not sure if there's still backwards compatibility; you can try that with a simple example. However if you are starting to write an app you should use path:
path('api/<str:encoded_url>/', view_action)
To avoid confusion with a stantard path to view in your app, I do not recommend using the path converter instead of the str (the former lets you match /, while the other does not).
You can get more help for transitioning from url to path with this article.
Second step, get the encoded_url as an argument in the view. You need to decode it: to pass a url inside the get url, you use ASCII encoding that substitutes certain reserved characters for others (for example, the forward slash).
You can encode and decode urls easily with urllib (there are other modules as well). For Python 3.7 syntax is as follows (docs here)
>>> urllib.parse.quote("http://www.google.com")
'http%3A//www.google.com'
>>> urllib.parse.unquote('http%3A//www.google.com')
'http://www.google.com'
Remember: if you pass the url without quoting it won't match: you are not accepting matches for slashes with that path expression. (Edit: quote method default does not convert forward slashes, for that you need to pass: quote(<str>, safe='')
So for example your GET call should look: /api/http%3A%2F%2Fwww.google.com. However it's better if you pass the URL as a get parameter and in the paths you only care aboubt readability (for example /api/name_to_my_method?url=http%3A%2F%2Fwww.google.com). Path engineering is important for readability and passing a quoted URL through is usually not ebst practice (though perfectly possible).
Django 2.0 is providing the Path Converters to convert the path parameters into appropriate types, which also includes a converter for urls, take a look at the docs.
So, your URLs can be like this:
path('api/<path:encoded_url>/', PerformImgSegmentation.as_view()),
So, the path converter will Matches any non-empty string, including the path separator, '/'. This allows you to match against a complete URL path rather than just a segment of a URL path as with str.
Then in the view, we can simply get our URL values from kwargs like this:
img_url = self.kwargs.get('encoded_url')
print(img_url)
Are you trying to pass the url https://i.imgur.com/TGJHFe1.jpg as a parameter from the django template to the view ?
You could simple write in your app's url.py:
path(api/<path:the_url_you_want_to_pass>', PerformImgSegmentation.as_view())
Please have a look at this article.

Django urls.py mistaking two close urls

i'm adding forms to my app to modify my lobbys (my custom model).
In urls.py, here is my urlpattern:
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^lobbys/$', views.LobbyListView.as_view(), name='lobbys'),
url(r'^lobby/(?P<pk>[\w-]+)/$', views.LobbyDetailView.as_view(), name='lobby-detail'),
url(r'^lobby/create/$', views.LobbyCreate.as_view(), name='lobby_create'),
url(r'^lobby/(?P<pk>\d+)/update/$', views.LobbyUpdate.as_view(), name='lobby_update'),
url(r'^lobby/(?P<pk>\d+)/delete/$', views.LobbyDelete.as_view(), name='lobby_delete'),
]
The problem is the following:
The third url is supposed to link to a single lobby template identifed with a UUID field as the primary key. Without the three last lines everything worked fine, but when I added my three urls for the forms, I'm getting the error
Exception Value: ["'create' is not a valid UUID."]
I understand urls.py is taking "create" as a primary key instead of considering it as an urls to an other view.
How can I bypass this problem?
Thank you very much.
You need to change the ordering of the url patterns
url(r'^lobby/create/$', views.LobbyCreate.as_view(), name='lobby_create'),
url(r'^lobby/(?P<pk>[\w-]+)/$', views.LobbyDetailView.as_view(), name='lobby-detail'),
The issue is, since lobby-detail is looking for a alphanum pattern, it also matches the pattern lobby/create. The order matters in the regex patterns, so lobby_create is never matched. By changing the order, the issue would be resolved

Best way to redirect url with extra trailing slashes in Django?

What is the best way to redirect a url like "mywebsite.com///" to "mywebsite.com/" in django?
Is there a setting that I can use in the settings.py file that is kind of the opposite of APPEND-SLASH or do I have to use
from django.views.generic.simple import redirect_to
and add a urlpattern in the urls.py file?
Edit:
I not trying to just make the webpage the same as "mywebsite.com/" i'm trying to get the actual url to change to "mywebsite.com/". Sorry for the confusion.
If you want to do this at the application level I'd avoid creating new urlconf rules, specially if it's a global thing.
You can make your own middleware to handle this redirect automatically, as django does in the common middleware for appending slashes using the APPEND_SLASH setting here is the code for reference: https://github.com/django/django/blob/master/django/middleware/common.py#L66-80
Also you may find the solution on this blog post useful: http://gregbrown.co.nz/code/append-or-remove-slash/
You should add a url pattern in the urls.py file that will match this url, with the added slashes, if you wish.
Each pattern is just a regular expression, so you can tell it to match any url with extra slashes pretty easily.
urlpatterns = patterns('django.views.generic.simple',
('^your/url/*$', 'redirect_to', {'url': '/your/url/'}),
)
By adding /* to the url pattern it will match /your/url/ with any number of slashes after it.

Categories

Resources