Django Rest API Url Pattern to handle . (dot) symbol - django

Creating Django REST API, Need suggestions to handle the .(dot char) in the urlpatterns. Below is the example detail:
I have a Model (test) with name as one of the fields and name value is of format ABC.XYZ
Below URL pattern does not work when name = ABC.XYZ
url(r'^tests/(?P<string>[\w\-]+)/$', views.tests.as_view(), name='api_tests_name')

You can add the dot to the character group in the regex:
url(r'^tests/(?P<string>[\w\-.]+)/$', views.tests.as_view(), name='api_tests_name')
So now you make a request with tests/foo.bar/ as path for example.

Related

Django - Redirect uppercase urls to lowercase

In my Django apps, I have many urls including /(?P<project_name>[_\w]+)/.
The project_name is defined by users and it is an attribute of the Project model.
I've added a validator on the project_name to check if it's lowercase.
So new names are all lowercase but some old names include uppercase characters.
I would like to change all the names stored to make them lowercase but at the same time, I don't want users to get an error when trying to access to one of the url with the old project name including uppercase characters.
As I have many urls and many views, I don't want to update each to manually .lower() the project_name.
Is there a way to redirect all urls including /<project_NAME>/ to /<project_name>/?
Hacky way with decorators
You could create a decorator for all your views that use a project_name:
def project_lowercase(_func=None):
def checkLowercase(func):
#functools.wraps(func)
def wrapper(*args, **kwargs):
request = args[0]
project_name = args[1]
if not project_name.islower():
return HttpResponseRedirect(reverse(your_url_name, kwargs{'project_name' = project_name.lower()))
return func(*args, **kwargs)
return wrapper
return checkLowercase(_func)
Replace your_url_name with whatever you named your url route, then import the function and add the decorator above each view function:
#project_lowercase
def view_project(request, project_name):
# ...
return "Hello World!"
Slugs would be better
Alternitively as suggested in the comments and a better solution you should use a slug to store urls for your projects, have a look here to see how to add them to your models and generate slugs.
To move your existing data to use slugs or just to update project names you can create a data migration that will alter existing data in your database.
The first option I would suggest is to avoid regular expressions, switch to path for your urlpatterns and use custom url converter for your project names.
In case you want to keep using regular expressions, you could restrict your pattern to only accept lower case project names /(?P<project_name>[_a-z0-9]+)/. After that add url pattern, which is (effectively) the same as your current one /(?P<project_name>\w+)/ (note missing _ - \w already includes that) to match all project names, including the legacy ones, the view for that pattern would redirect to your first view with the lower case project_name.

what does {variable_name} in an url pattern mean in Django?

I'm reading Django Rest Framework documentation on router (https://www.django-rest-framework.org/api-guide/routers/) and encounter this:
^accounts/{pk}/$
I understand ^ means start of line, $ means end of line and everything but {pk}. What does it mean?
It means that an url pattern that includes a primary key, si valid. In the case of the documentation you are consulting, it means that the following url pattern is valid: accounts/121/. What SimpleRouter will do with it, is that urls that contain a primary key ({pk}), will be used to update or delete the accounts record with such primary key. In the example, account with primary key '121' would be retrieved, updated or deleted through such url.
This "variable_name" is received as a parameter by the view method or class method.

uuid as keyword argument <pk> in django urls.py

I am using a uuid4 as id in some django models. Thats why I cannot use <int:pk> in the urls.py because it wont match. Is there another prefix I can use to match these uuids like a2182835-4518-cb95-8eaf-0d5a34105cb2 ?
You can use the uuid path converter instead of int. From the docs
uuid - Matches a formatted UUID. To prevent multiple URLs from mapping to the same page, dashes must be included and letters must be lowercase. For example, 075194d3-6885-417e-a8a8-6c931e272f00. Returns a UUID instance.
So for your purposes changing <int:pk> to <uuid:pk> should do the trick

What would be Djnago's url pattern to match and fetch out a url (coming appended to site's domain as a GET request)?

Suppose my site's domain is mysite.com , now whenever a request comes in this form : mysite.com/https://stackoverflow.com :I want to fetch out this url "https://stackoverflow.com" and send it to the corresponding view.
I have tried this pattern :
url(r'^(?P<preurl>http[s]?://(?:[a-zA-Z]|[0-9]|[$-_#.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)$',prepend_view)
regex of which matches the incoming appended url and assigns variable preurl the value "https://stackoverflow.com", which I access in corresponding view function .
This works fine for above example but my url pattern is failing in case of some exceptional urls..
Please suggest a robust url pattern by taking into consideration all exceptional urls too, like the following:
ftp://ftp.is.co.za/rfc/rfc1808.txt
http://www.ietf.org/rfc/rfc2396.txt
ldap://[2001:db8::7]/c=GB?objectClass?one
mailto:John.Doe#example.com
news:comp.infosystems.www.servers.unix
tel:+1-816-555-1212
telnet://192.0.2.16:80/
urn:oasis:names:specification:docbook:dtd:xml:4.1.2
That is, if a request comes like :
mysite.com/ldap://[2001:db8::7]/c=GB?objectClass?one
I should be able to get the value "ldap://[2001:db8::7]/c=GB?objectClass?one" in variable preurl
You don't have to make this type of complex url pattern, First, make a URL pattern that matches everything.
url(r'^.*/$', views.fast_track_service, name='fast_track'),
and append it to the end in urlpatterns in your urls.py then in your view, Use request object, So You can get the full path of get request with this method,
fast_track_url = request.get_full_path()[1:]
and then once you got the url try validating that with URLValidator like this.
if not 'http://' in fast_track_url and not 'https://' in fast_track_url:
fast_track_url = 'http://' + fast_track_url
url_validate = URLValidator()
try:
url_validate(fast_track_url)
except:
raise Http404
If you want to validate other complicated URL like mailto etc, then you can write your own validator.

Making a Regex Django URL Token Optional

You have a URL which accepts a first_name and last_name in Django:
('^(?P<first_name>[a-zA-Z]+)/(?P<last_name>[a-zA-Z]+)/$','some_method'),
How would you include the OPTIONAL URL token of title, without creating any new lines. What I mean by this is, in an ideal scenario:
#A regex constant
OP_REGEX = r'THIS IS OPTIONAL<title>[a-z]'
#Ideal URL
('^(?P<first_name>[a-zA-Z]+)/(?P<last_name>[a-zA-Z]+)/OP_REGEX/$','some_method'),
Is this possible without creating a new line i.e.
('^(?P<first_name>[a-zA-Z]+)/(?P<last_name>[a-zA-Z]+)/(?P<title>[a-zA-Z]+)/$','some_method'),
('^(?P<first_name>[a-zA-Z]+)/(?P<last_name>[a-zA-Z]+)(?:/(?P<title>[a-zA-Z]+))?/$','some_method'),
Don't forget to give title a default value in the view.
In case your are looking for multiple optional arguments, without any required ones, just omit "/" at the beginning, such as:
re_path(r'^view(?:/(?P<dummy1>[a-zA-Z]+))?(?:/(?P<dummy2>[a-zA-Z]+))?(?:/(?P<dummy3>[a-zA-Z]+))?/$', views.MyView.as_view(), name='myname'),
which you can browse at:
http://localhost:8000/view/?dummy1=value1&dummy2=value2&dummy3=value3