I am making a simple code editor. Each user is allocated a six character long id which needs to be appended to the URL. So, if some accesses the page on localhost:8000/myapp/, the URL needs to change to localhost:8000/myapp/<token>.
I am using the following function to generate that token key -
def id_generator(self,size=6, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
I have created a middleware but I am confused how to proceed further. What should I use - process_request() or process_response()?
And how show I define either of them, so that URL changes but functionality remains the same.
If I am right :
Write a view for localhost:8000/myapp/ In this view generate your token and then redirect it to new url from the view .
def mytoken(request):
token = '0-wedfbdhfgm'
return redirect(localhost:8000/myapp/token='+token)
This is a two-step process. You need to create
a view with a matching url to retrieve your individual token
a view with a matching named url to provide the result to the user
urls.py
...
url(r'^myapp/(?P<token>\w+)/$', views.your_user_result_view, name='your-user-result-view'),
url(r'^myapp/$', views.your_token_appender_view, name='your-token-appender-view'),
...
views.py
...
def your_user_result_view(request):
...
def your_token_appender_view(request):
token = ...
redirect(reverse('your-user-result-view',kwargs={'token':token}))
...
Related
i have a table which include all users and two columns at the end (Edit,Delete) and i just enabled the delete column, the issue is when i click on the delete icon the record will be deleted but the url will stuck on the delete function even if i used return render(request,'getUsersInfo.html') which is get all records function
Model Name: Users
urls:
from django.urls import path
from django.conf.urls import url
from . import views
urlpatterns = [
path('signup.html',views.signup,name=''),
path('getUsersInfo.html',views.getAllUsers,name=''),
url(r'^deleteUser/(?P<fullname>\D+)/$',views.deleteUser, name='deleteUser'),
# this is how to call a function without parameters url(r'^deleteUser/$',views.deleteUser, name='deleteUser'),
in the same view i have 3 functions (singup "add user", getAllUsers "get all the records to the table,deleteUser)
views:
def getAllUsers(request):
print("getAllUsers")
thesearchValue = ''
if 'SearchValue' in request.GET:
thesearchValue = request.GET['SearchValue']
print(request.GET['SearchValue'])
allUsers = User.objects.filter(fullname__icontains=thesearchValue)#all()
# return render(request,'getUsersInfo.html',{'allUsers':allUsers})
return render(request,'getUsersInfo.html',{'allUsers':allUsers})
else:
print("Empty")
allUsers = User.objects.all()
return render(request,'getUsersInfo.html',{'allUsers':allUsers})
def deleteUser(request,fullname):
print('delete the user')
todelete = User.objects.filter(fullname=fullname)
todelete.delete()
return render(request,'getUsersInfo.html')
Notice that i used return render(request,'getUsersInfo.html') which should call getAllUsers(request): but the url stuck on http://127.0.0.1:8000/deleteUser/John/
Rendering the same template as another view does not mean that you will somehow call other views. A template is nothing more than a tool to specify how to convert context data to a string, that is passed as HTTP response. You can use the same template in multiple views, and a view can render multiple templates.
You can make use of redirect(..) [Django-doc] to return a HTTP redirect response (302):
from django.shortcuts import redirect
def deleteUser(request,fullname):
print('delete the user')
todelete = User.objects.filter(fullname=fullname)
todelete.delete()
return redirect(getAllUsers)
Note: A GET request is not supposed to have side-effects, hence removing
objects when a user makes a GET request, is not compliant with the HTTP
standard. Therefore it might be better to remove a User with a POST request.
I am looking to add email account verification in Django and found a nice open source code that I can adopt.
But there is one line which I'm not familiar with.
Why does the function "password_reset_confirm" need to return two **kwargs in separate brackets and
how each of them is used in the class "PasswordResetConfirm"?
This question might be related to Python rather than Django. But anyway, thank you for your help!
urls.py
url(r"^password/reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-
z]{1,13}-[0-9A-Za-z]{1,20})/$",views.password_reset_confirm, name="reset-
password-confirm",)
views.py
from django.contrib.auth import views as django_views
class PasswordResetConfirm(django_views.PasswordResetConfirmView):
template_name = "account/password_reset_from_key.html"
success_url = reverse_lazy("account:reset-password-complete")
token = None
uidb64 = None
def form_valid(self, form):
response = super(PasswordResetConfirm, self).form_valid(form)
account_events.customer_password_reset_event(user=self.user)
return response
def password_reset_confirm(request, uidb64=None, token=None):
kwargs = {
"template_name": "account/password_reset_from_key.html",
"success_url": reverse_lazy("account:reset-password-complete"),
"token": token,
"uidb64": uidb64,
}
return PasswordResetConfirm.as_view(**kwargs)(request, **kwargs)
First variable (uidb64) is just base64-encoded ID of user, extracted from database. By this field Django can determine which user is requesting password reset.
Second variable (token) is an actual reset token that is used to verify user request. User can get this token only from email that was sent to him, so this verifies that user has access to provided email address, so we can proceed with password reset.
Why we can't use token alone? There are 2 reasons for that
Django doesn't store password reset tokens in database. A lot of other frameworks will do that and after user clicks password reset URL, token will be found in database and from that database entry, user requesting reset will be determined. Instead, Django uses some clever cryptography methods and generates this token from SECRET_KEY stored in database, current user password hash and time of generating this token. After that, only time can be extracted from token and by fetching user data together with SECRET_KEY from settings, Django can verify that password reset token is valid for specified user. Time of token generation is here, so every token can expire after some time.
User ID cannot be easily embedded in token, as time is, as User ID format can be customized (you can embed your own user model that uses for example UUID instead of numerical value). That's why Django is encoding this ID using Base64 - it guarantees that every format of user ID can be easily embedded in URL. For that reason, User ID can have different length and format, so it won't be easy to extract it from token string.
As for passing kwargs twice, here is quick explanation by example:
In python, you can return function from calling any other function or method (most often those kind of functions are called factories):
def some_factory():
def some_function():
print('abc')
return some_function
my_function = some_factory()
In this example, print won't be called as we are not executing some_function, some_factory returns it, so we can use it later:
my_function()
Now this print will be called and we will see abc in console output. But instead of assigning returned function to some variable or passing it somewhere, you can call it immediately:
some_factory()()
This is where the second parentheses come from. Of course both functions can take some arguments, then you will provide arguments for factory inside first pair of parentheses and arguments to some_function in second.
Back to your example, it is actually invalid, you shouldn't pass full kwargs to as_view in PasswordResetConfirm. It should take only first two (template_name and success_url). Actual view (second parentheses) should take other two (token and uidb64).
2nd thing that is wrong in your code is that you're calling as_view on every request. It is designed to be called only once, when creating this view. Instead of wrapping it in separate function, use it directly in your urls.py:
url(
r"^password/reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$",
PasswordResetConfirm.as_view(
template_name="account/password_reset_from_key.html"
success_url=reverse_lazy("account:reset-password-complete"),
), name="reset-password-confirm",
)
I'm building a SSO login meant to be used from links send by emails.
Each link should auto-connect the user (SSO), and be clickable multiple times (they have a TTL, which depends on the email)
It works fine, but I'm concerned about the end-user sharing his url on social networks (basically copy/pasting the url, which contains the SSO token), allowing anyone following the link to be logged in automatically.
My first attempt was to try to remove the GET SSO_TOKEN parameter, from my SSOMiddleware, as follow:
if remove_token_middleware:
request.GET._mutable = True # GET is not mutable by default, we force it
# Remove the token from the url to avoid displaying it to the client (avoids sharing sso token when copy/pasting url)
del request.GET[SSO_TOKEN_PARAM]
request.GET._mutable = False # Restore default mutability
return login(request, user) if service.get("auto_auth") else None
Basically, my thought was that since the SSO_TOKEN is in the request.get object, removing it from it would eventually change the url where the user gets redirected
In my controller, here is how the user gets "redirected" (using render)
return render(request, 'campagne_emprunt/liste_offres_prets.html', locals())
When using render, there is no redirection, and the SSO token is still visible in the URL (in the browser address bar).
Is there a way to somehow tell Django to change the destination url, on the fly?
So in order to redirect, there is a builtin redirect function of Django that you use instead of rendering I think .. give it a shot,
from django.shortcuts import redirect
def redirect_view(request):
response = redirect('/redirect-success/')
return response
and for reference-
https://realpython.com/django-redirects/
I'm working on a project, I want to code the following steps
=> The user in page A wants to access to page B, so the user in page A will redirect to page B after validating the form, then :
Creating a random url
The user is redirected to that random URL
the user cant access to page B if he doesn't validate the form on page A
I use django 2.1
Thanks for your help :)
You can do this with reverse from django.url and can able to pass random args or kwargs link.
Say your urls are be like
urlpatterns = [
path('articles/', your_article_view),
path('articles/<slug:slug>/', your_article_slug_view),
]
and from your article_view you can redirect to article_slug_view as
reverse('articles', args=['hello'])
'/articles/hello' # url
you can generate uuid and pass it by this, this will always make sure random different url everytime. Whatever you want to do.
First of all, let me say that this looks like an anti-pattern.
On Django you can set url's that matches some expression:
path('secret/<slug:passwd>/', views.super_secret, name="secret")
Then, you can redirect to this url with a key:
if form.is_valid():
some_key = #some random key
cache.set(some_key, True, 3)
return HttpResponseRedirect(reverse('secret', args=(some_key,)))
And check your key from cache on view secret.
My views.py code:
from django.template import Context, loader, RequestContext
from django.http import HttpResponse
from skey import find_root_tags, count, sorting_list
from search.models import Keywords
def front_page(request):
if request.method == 'get' :
str1 = request.getvalue['word']
fo = open("xml.txt","r")
for i in range(count.__len__()):
file = fo.readline()
file = file.rstrip('\n')
find_root_tags(file,str1,i)
list.append((file,count[i]))
sorting_list(list)
for name, count in list:
s = Keywords(file_name=name,frequency_count=count)
s.save()
fo.close()
return HttpResponseRedirect('/results/')
else :
str1 = ''
list = []
template = loader.get_template('search/front_page.html')
c = RequestContext(request)
response = template.render(c)
return HttpResponse(response)
def results(request):
list1 = Keywords.objects.all()
t = loader.get_template('search/results.html')
c = Context({'list1':list1,
})
return HttpResponse(t.render(c))
#this for everyone.
the flow is this:
1) I run my app on the server .
2)It shows me the search page due to the else part of the view "def front_page(request)", now I want to execute the if part of the view "def front_page(request)" because I want to execute my python code written there and the redirected to the view "def results(request)", how can I do that ?
3) what should I mention in "action" of the front_page.html and in urls.py so that I can get back to the same view again. because I could'nt get back to the same view that I want it is repetitively showing me the same search page.Please help.
To enlarge upon the answer posted by #Barnaby....by using action='#' your form will be posted to the same url as the url used in the get request for the form.
Then in your view code, you have logic that says - if the request for this url is a GET request then do the work to configure the form, otherwise, you assume it is a POST and then you can handle the response.
Additionally I would advise that the your view explicitly checks that the request is a POST and if not make the assumption that it is a GET, rather than the other way around (as you have it), this is safer, as GET and POST are not the only request types, and you definitely need to know that you are dealing with a POST request if you want to deal with variables submitted in the POST request.
Hope that helps
Short answer: action="#". This is a HTML trick to post back to the current URL.
The general answer to how to reference a view in a template is to use the url tag. You may also want to consider using Django's forms functionality.