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

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

Related

Parse &-character in GET query using Django and Vue

We are using axios to pass GET request to our django instance, that splits it into search terms and runs the search. This has been working fine until we ran into an edge case. We use urlencode to ensure that strings do not have empty spaces or others
So generalize issue, we have TextField called "name" and we want to search for term "A & B Company". However, issue is that when the request reaches django.
What we expected was that name=A%20&%20B%20Company&field=value would be parsed as name='A & B Company' and field='value'.
Instead, it is parsed as name='A ' 'B Company' and field='value'. The & symbol is incorrectly treated as separator, despite being encoded.
Is there a way to indicate django GET parameter that certain & symbols are part of the value, instead of separators for fields?
You can use the lib urllib
class ModelExample(models.Model):
name = models.TextField()
# in view...
from urllib.parse import parse_qs
instance = ModelExample(name="name=A%20&%20B%20Company&field=value")
dict_qs = parse_qs(instance.name)
dict_qs contains a dict with decoded querystring
You can find more informations about urllib.parse here: https://docs.python.org/3/library/urllib.parse.html

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.

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

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.

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.

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