Django Save Path into Variable - django

I have a django path that passes the URL I need, but I want to store it into a variable which I can use in a mailing API the path is:
path('activate/(<uidb64>[0-9A-Za-z_\-]+)/(<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})', views.activate, name='activate'),
"uid": urlsafe_base64_encode(force_bytes(account.pk)),
'token': password_reset_token.make_token(account),
I want the string to have a value similar to this: http://127.0.0.1:8000/auth/activate/(NDM%5B0-9A-Za-z_%5C-%5D+)/(as9osn-a59ae3d7196bb1fa693e770fb87f19c1%5B0-9A-Za-z%5D%7B1,13%7D-%5B0-9A-Za-z%5D%7B1,20%7D)
I am getting this: http://127.0.0.1:8000/auth/activate/NTQ/asbda1-165d68dbe6fee8c47f5099c4ab709c48

You are using regex-syntax instead of path syntax. You thus should use the re_path(…) function [Django-doc] to specify a regex, or convert it to a path syntax. We thus can implement this with:
from django.urls import re_path
urlpatterns = [
# &vellip;,
re_path('activate/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', views.activate, name='activate'),
# &vellip;
]

Related

django use of quotes in url template tag

In myusers.urls I have set app_name = 'users' and name='users' in the urlpatterns.
Why are quotes needed around users:users in the following:
/users
is that a shortcut? Do the quotes tell django to resolve the address? Would the following work?
/users
urls.py
from django.urls import path
from . import views
app_name = 'users'
urlpatterns = [
path('', views.index, name='index'),
path('users/', views.users, name='users'),
]
views.py
from django.shortcuts import render
from myusers.models import *
# Create your views here.
def index(request):
return render(request, 'myusers/index.html')
def users(request):
users = AllUser.objects.all()
return render(request, 'myusers/users.html', {'users':users})
Unquoted arguments are template variables, not python variables, not module references, but only names with values provided to the template. This is the "context" passed to templates from views, where the key is the variable name. It can also be variables inside for loops and with constructs.
Quoted arguments are strings.
The URL tag uses its string arguments to resolve urls, by using Django's reverse and that's it. The string "users:users", refers to the URL namespace "users" and the view with name "users".

Utilizing Django url resolver vs. re-inventing the request.path parsing wheel

Let's say I had the following array:
sub_urls = [
'/',
'/<uuid:id>',
'/test',
'/test/<uuid:id>'
]
The URL stings are very similar to what you'd find in Django's urlpatterns
my question:
can django.url.resolve be used to find the pattern in the sub_urls array given a path string like /test/189e8140-e587-4d5d-ac5c-517fd55c67bc without me having to re-invent the wheel here?
PLEASES NOTE: this isn't a question about how I route from urls to views in Django. Please don't tell me how to "solve it with urlpatterns, re_path etc." This is about utilizing this same mechanism by which django matches up a URL with a view --- for a COMPLETELY different purpose. I can write this myself, but I wanted to know if there's a way to re-use what Django has as it CLEARLY has the same needs when parsing request.path into the correct view.
Since django.urls.resolve calls get_resolver which creates a URLResolver (through _get_cached_resolver), you can instead create a URLResolver yourself:
# Define an empty view
def empty_view(*args, **kwargs):
return None
# Define the urlpatterns
from django.urls import path
sub_urls = [
'/',
'/<uuid:id>',
'/test',
'/test/<uuid:id>'
]
urlpatterns = [path(u, empty_view) for u in sub_urls]
# Create a resolver
from django.urls.resolvers import URLResolver, RegexPattern
resolver = URLResolver(RegexPattern(r'^'), urlpatterns)
# Match a path
# Returns a django.urls.resolvers.ResolverMatch object
result = resolver.resolve('/test/189e8140-e587-4d5d-ac5c-517fd55c67bc')
print(result)
print(result.route)
The above code will output:
ResolverMatch(func=__main__.empty_view, args=(), kwargs={'id': UUID('189e8140-e587-4d5d-ac5c-517fd55c67bc')}, url_name=None, app_names=[], namespaces=[], route=/test/<uuid:id>)
/test/<uuid:id>
If you're set on using django.urls.resolve, you could move urlpatterns to a module, let's say my_urls:
# Define an empty view
def empty_view(*args, **kwargs):
return None
# Define the urlpatterns
from django.urls import path
sub_urls = [
'',
'<uuid:id>',
'test',
'test/<uuid:id>'
]
urlpatterns = [path(u, empty_view) for u in sub_urls]
Notice we had to remove the / suffixes from the URLs above because _get_cached_resolver creates a RegexPattern that starts with /.
And then pass the module name as the second argument to resolve:
# Configure settings (only needed when this is not being run in an existing Django app)
from django.conf import settings
settings.configure()
# Match a path
# Returns a django.urls.resolvers.ResolverMatch object
from django.urls import resolve
result = resolve('/test/189e8140-e587-4d5d-ac5c-517fd55c67bc', urlconf='my_urls')
print(result)
print(result.route)
I don't believe the caching of _get_cached_resolver should be an issue as #Clepsyd mentioned since functools.lru_cache caches depending on the arguments it receives.

Building URL from name

I've got a url of 'accounts:produce_setup' (i.e. namespace/app is 'accounts' and name of url is 'product_setup'). I'd like to build the full url associated with this view and pass it as context into a template.
How would I go about doing this? Would I use build_absolute_uri()?
Thanks!
you should include your app in project_name/urls.py and bind your application to special URL pattern like this:
from account.urls import urlpatterns as account_urlpatterns
urlpatterns = [
url(r'^account/', include(account_urlpatterns, namespace='account')),
url(r'^admin/', admin.site.urls),
]
and after this in your account/urls.py you can implement your urlpatterns and set your special name for each url like this:
from django.conf.urls import url
from .views import produce_setup_view
urlpatterns = [
url(r'^produce_setup/$', produce_setup_view, name='produce_setup')),
]
at the end now you can use them in your template and views or any python file in your django project like this:
.py in django project:
from django.urls import reverse
url_string = reverse('account:produce_setup')
print(url_string)
>>> '/account/produce_setup/'
in template:
Good Luck :)
Actually, you don't need to. You can simply use {% url "accounts:product_setup" %} in template. For more details check here. And if you want to build the url is views(maybe for other reasons) you can use reverse.

Check(conditional) if the current url is the same with a url declared in path

In the main urls.py I have:
urlpatterns = [
path('items/', include('items.urls', namespace='items')),
....
]
In items urls.py I have:
urlpatterns = [
path('item/add/', ItemCreateView.as_view(), name='create_item'),
]
I want to check in a view/dispatch() if the current page url is the same with the one in the path, something like:
if self.request.path == 'items:create_items'
You can use reverse to convert the namespaced pattern name items:create to the URL.
from django.urls import reverse
if self.request.path == reverse('items:create_items'):
Depending on your server setup and whether you are concerned about the querystring, you may want to use request.path_info or request.get_full_path() instead of request.path.

Changing a old Django URL to the new paths

So I am making a new site in Django 2.0 and was following this tutorial on making a user registration form with an activation email and my understanding of the new Django 2 is not good enough so was asking what would be the Django 2 equivalent of this URL
url(r'^activate/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', views.activate, name='activate'),
There is no straight conversion for your path you could either use a converter as stated in the docs to convert the token. Here the example from the docs:
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
register the converter
from django.urls import path, register_converter
from . import converters, views
register_converter(converters.FourDigitYearConverter, 'yyyy')
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<yyyy:year>/', views.year_archive),
...
]
or you can just regex the path like you currently are:
from django.urls import path, re_path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
re_path(r'^activate/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', views.activate, name='activate')
]
I would just stick to the regex using re_path since you know it works and its already done.
Here is the link to the docs:
https://docs.djangoproject.com/en/2.0/topics/http/urls/