Open leferaycloud opened 6 years ago
Hi @leferaycloud. Firstly - sorry it took so long for me to respond.
I believe that you may have confused the REST architecture with a traditional single layer. In djoser we expect that your backend is used to provide API for mobile apps or your frontend layer (e.g. Single Page App) and therefore the process you have described is not something we had in mind with djoser.
Although - what you say is possible I'm not sure why you would need REST API if you wish to handle everything within the single Django layer. Here is how you would usually handle user activation:
users/create/
.users/activate/
with POST with uid
and token
, which indeed you extract from the URL GET params.If for whatever reason you want to handle everything within Django, my first thought would be to use requests to call the djoser activation URL, but as I said it's not how you would usually want to do this.
Hope this answers your question.
Hi, i have the same question. I understand we can create a page to redirect the data to the activate url as a POST. However I would like the user to be able to activate directly by clicking on that URL. Is that somehow possible without having to create my own GET API?
Hi @lgalant.
At the moment - no, it's not possible, mostly because Djoser has been created with SPA and mobile apps in mind and therefore it would be a terrible UX flaw to make users visit e.g. api.example.org
to activate account.
I doubt that in near future we will decide to bring such view into djoser, but it's very simple to create it if you really need it - in spare time I'll add it to djoser example docs with a disclaimer that it is not the architecture, for which djoser was made.
@piotr-szpetkowski Thanks for your quick reply, It'd be really helpful if you can write such view as an example.
Now supposing I'm developing a mobile app and I want to verify the email of my users. What is the recommended behavior for the user to confirm that the email he provided belongs to him, using djoser ?
Thanks again!
Working on this issue right now, maybe it will be usable for others.
I created APIView:
from djoser.conf import django_settings
class ActivateUserByGet(views.APIView):
def get(self, request, uid, token, format = None):
payload = {'uid': uid, 'token': token}
url = '{0}://{1}{2}'.format(django_settings.PROTOCOL, django_settings.DOMAIN, reverse('user-activate'))
response = requests.post(url, data = payload)
if response.status_code == 204:
return Response({'detail': 'all good sir'})
else:
return Response(response.json())
and added it to mu urls:
path('activate/<str:uid>/<str:token>/', ActivateUserByGet.as_view()),
django_settings.PROTOCOL
and django_settings.DOMAIN
are used for bulding proper url. Hope it helps you!
response = requests.post(url, data = payload) if response.status_code == 204:
Django is singlethreaded. The "requests" will never be fulfilled, because maib process will be busy waiting for a response.
Even if you run django in several threads (with gunicorn e.g.), this is still a suboptimal strategy to call django from django. You should rather simply copy the existing POST view and create a GET one that does the same.
Still I don't think that doing activation with GET fits into REST architecture. What do you think @dekoza @haxoza ? Will we implement it or can I close?
@zefciu Could you please elaborate on that?
From what I'm seeing here, I can't settle on whether it's more acceptable to handle everything in Django (sounds more appropriate to me) or cycle through the network and web server again with a POST request to activate account.
Working on this issue right now, maybe it will be usable for others.
I created APIView:
from djoser.conf import django_settings class ActivateUserByGet(views.APIView): def get(self, request, uid, token, format = None): payload = {'uid': uid, 'token': token} url = '{0}://{1}{2}'.format(django_settings.PROTOCOL, django_settings.DOMAIN, reverse('user-activate')) response = requests.post(url, data = payload) if response.status_code == 204: return Response({'detail': 'all good sir'}) else: return Response(response.json())
and added it to mu urls:
path('activate/<str:uid>/<str:token>/', ActivateUserByGet.as_view()),
django_settings.PROTOCOL
anddjango_settings.DOMAIN
are used for bulding proper url. Hope it helps you!
Hey @pplonski How did this solution turn out for you?
Hi @sudomann, it works, I'm sending link with email, and it has link for GET request, which triggers POST request.
I'm using @pplonski approach and it works for me aswell.
hi @pplonski It gives me a error. AttributeError: 'Settings' object has no attribute 'PROTOCOL'
@safakat have you set PROTOCL in your settings? It is needed to construct the url.
no.can you send me the protocol code?
I don't know what protocol are you going to use, but I have used the following:
PROTOCOL = "https"
This is my djoser setting. DJOSER = { 'PASSWORD_RESET_CONFIRM_URL': '/password/reset/confirm/{uid}/{token}', 'USERNAME_RESET_CONFIRM_URL': '/username/reset/confirm/{uid}/{token}', 'ACTIVATION_URL': '/activate/{uid}/{token}', 'SEND_ACTIVATION_EMAIL': True, 'SEND_CONFRIMATION_EMAIL':True, 'SERIALIZERS': {}, }
And what will be the domain? currently i am doing it in localhost.
The domain at which you would like to get the POST request (it will be your domain).
and the last problem is:
Exception Value: | Reverse for 'user-activate' not found. 'user-activate' is not a valid view function or pattern name.
looks like you dont have djoser urls set
path('admin/', admin.site.urls), path('auth/',include('djoser.urls')), path('auth/',include('djoser.urls.jwt')), path("api/data/",include("data.urls")),
i did it with this
def ActivateUserAccount(request, uidb64=None,token=None):
#print(force_text(urlsafe_base64_decode(uidb64)))
#print(token)
try:
uid = force_text(urlsafe_base64_decode(uidb64))
#print(type(uid),uid)
user = User.objects.get(pk=uid)
print(user)
except User.DoesNotExist:
user = None
if user and default_token_generator.check_token(user,token):
user.is_email_verified = True
user.is_active = True
user.save()
login(request,user)
print("Activaton done")
else:
print("i dont know ")
users/activate/ has now changed to users/activation/
Is anybody using users/activation/ endpoint successfully? When I make POST request to users/activation/ I get a 404 not found.
This is the POST request:
curl -X POST http://127.0.0.1/auth/users/activation/ --data 'uid=myuid&token=mytoken'
My urls.py is as follows:
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('api.urls')),
re_path(r'^auth/', include('djoser.urls')),
]
What I'm doing wrong? Thanks in advance!
@storrabadellaf how did you generate your uid? I have a similar problem
Any update on how to do this without the development server hanging?
@theSekyi , @luke-goddard I've added these to my settings file
DEBUG = True
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
PROTOCOL='http'
DOMAIN= '127.0.0.1:8000'
with the email backend attribute after poting a new user on auth/create it will show the activation email in terminal in this pattern '#/activate/{uid}/{token}', ` Content-Transfer-Encoding: 7bit
You're receiving this email because you need to finish activation process on 127.0.0.1:8000.
Please go to the following page to activate account: http://127.0.0.1:8000/#/activate/MTE/b0y14v-85c128ab17129709d256c155f8a7ef61
Thanks for using our site! ` while I'm running backend, in a new terminal I run the below command and I use the uid and token that is there in the activation link taht's exist in the terminal for the below command and it works for me and make the posted user activated .
curl -X POST http://127.0.0.1/auth/users/activation/ --data 'uid=myuid&token=mytoken'
Hope you understand, happy coding ;)
I am using DREF and Djoser for Authentication and User Registration. When a new user registers, Djoser sends an activation email with a link that does a GET request. In order to activate, I need to extract uid and token from the activation url and make a POST request for Djoser to be able to activate the user.
My environment is Python 3 and Django 1.11, Djoser 1.0.1.
Any help on how to handle this in Django / Djoser?
What I would like to do is to handle the get request in Django, extract uid and token and then make a POST request. I have extracted uid and token and would like to make a POST (within this GET request). I do not know how to make this POST request in the background.