get user with token django rest framework - python

sorry for my english. It is not good.
I work with rest framework django. I want to recover a user with his token. This Token must be sent via a post request
class GetUser(generics.ListCreateAPIView):
serializer_class = serializers.UserBasicSerializer
def get_queryset(self):
return models.Member.objects.filter()
def post(self, request, *args, **kwargs):
user = Token.objects.get(*args, **kwargs).user
i receive this error message
rest_framework.authtoken.models.MultipleObjectsReturned: get() returned more than one Token -- it returned 2!
thanks

Use:
user = Token.objects.filter(*args, **kwargs)
if user.exists():
user = user.last().user

The answer to your question is in the docs. Take a look here: http://www.django-rest-framework.org/api-guide/requests/#user
Basically, you just need to get from request the method user. For example:
def api_name_of_api(request):
user_data = request.user # Get username
user_data = request.user.id # Get user id
...

Related

How to get user object from Django DRF when logged in with TemplateView?

I am begginer in Djnago and logged in to my app with this code:
class LoginHandler(TemplateView):
def get(self, request, *args, **kwargs):
user = authenticate(request, email='jaxen#gmail.com', password='123456')
login(request, user)
return render(request, "login.html", context={})
But i need to detect logged in user in other app that use DRF.
I don't know how fetch the user.
I tried this code but not worked:
class OtherAppHandler(APIView):
def post(self, request):
print(f"user: {request.user}")
...
Thank you.
I think that api is stateless. In api, you need to pass the authorization token from the front end to call API and then get the user from the request.user inside api.
I think you need to fetch the user. Using get method.
def get(self, request):
user_data = request.GET.get('user', '')

Django REST How to Hash Password Correctly

I'm using dj_rest_auth to authenticate my users and there is a problem with registration. After I create a user with RegisterView that dj_rest_auth gives, django creates the user without a problem but password hashing is incorrect and thus I can not login with new created user.
This is my Register View:
registerview.py
class UserRegisterAPIView(RegisterView):
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
# user.set_password(make_password(request.data.get('password'))) Didn't work
user = self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(self.get_response_data(user),
status=status.HTTP_201_CREATED,
headers=headers)
def perform_create(self, serializer):
user = serializer.save(self.request)
create_token(self.token_model, user, serializer)
complete_signup(self.request._request, user,
allauth_settings.EMAIL_VERIFICATION,
None)
return user
EDIT: These are the same password but hashed differently(First one is dj_rest_auth's register view, second one is created in admin panel)
If I use the second password on other users, they successfully log in.
I think you have a typo in your create method.
Where you have the commented section:
user.set_password(make_password(request.data.get('password')))
It should actually be:
user.set_password(make_password(serializer.data.get('password')))
I'm not sure what the function make_password does there, but that should solve the problem.

Get data from a APIview in django rest framework

In my app I am trying to get the User data using a get request and it works in Postman but the problem occurs when I try to send the data from FrontEnd as we cannot send Body in get Request
URL:
path('user/meta/', UserDetails.as_view()),
Views.py
class UserDetails(APIView):
"""Get basic details of user"""
def get(self, request):
username = request.data["username"]
if User.objects.filter(username = username).exists():
user = User.objects.get(username = username)
print(user)
return Response({
'verified': user.verified,
})
else:
return Response("User doesn't exists", status=status.HTTP_400_BAD_REQUEST)
How should I modify it such that I can get the data from get request?
So, your requesting URL will become /user-info/?username=john
and then, use request.GET
username = request.GET.get("username","default_value")
The good practice is to use query params in such case,
so your url will look like,
/user-info/?username=john
and you modify your code to,
username= self.request.query_params.get('username')
I know this is an old topic and the question is answered, but just to underline that the queried data, you obtained from the user in the API should go through the Serializers (https://www.django-rest-framework.org/tutorial/1-serialization/) to at least somehow protect against unwanted values. This will also avoid you directly querying the database models.

How to test that a view is only accessed by staff users in Django

I am learning testing in Django, and have a view which I want to test. This view should only be accessed by staff users. Suppose the view is:
def staff_users(request):
....
# some logic
return HttpResponseRedirect('/repositories/')
if the request is coming from staff users, it should redirect to repositories otherwise I should get something like permission denied. I am starting with something like in tests.py.
def test_request_object(self):
self.user = User.objects.create_user(
username='abc', email='abc#gmail.com', password='1234')
request = HttpRequest()
# User send a request to access repositories
response = staff_users(request)
self.assertIsNone(response)
The problem is here I am not associating my request object with any users, and I also got to know about from django.contrib.admin.views.decorators import staff_member_required but not sure how to use them here. Could anyone tell me how should I test my view should only be accessed by staff users?
All you need to do is decorate your view which you want to protect as shown below:
#staff_member_required
def staff_users(request):
....
# some logic
return HttpResponseRedirect('/repositories/')
If you want a custom logic for testing instead of using django decorator then you can write your own decorator as well.
def staff_users_only(function):
def wrap(request, *args, **kwargs):
profile = request.session['user_profile']
if profile is True: #then its a staff member
return function(request, *args, **kwargs)
else:
return HttpResponseRedirect('/')
wrap.__doc__=function.__doc__
wrap.__name__=function.__name__
return wrap
and use it as:
#staff_users_only
def staff_users(request):
....
# some logic
return HttpResponseRedirect('/repositories/')
Edit
Association of sessions on request object for testing can be done as:
def test_request_object(self):
self.user = User.objects.create_user(
username='abc', email='abc#gmail.com', password='1234')
request = HttpRequest()
#create a session which will hold the user profile that will be used in by our custom decorator
request.session = {} #Session middleware is not available in UnitTest hence create a blank dictionary for testing purpose
request.session['user_profile'] = self.user.is_staff #assuming its django user.
# User send a request to access repositories
response = staff_users(request)
#Check the response type for appropriate action
self.assertIsNone(response)
Edit 2
Also it would be a far better idea to use django Client library for testing:
>>> from django.test import Client
>>> c = Client()
>>> response = c.post('/login/', {'username': 'abc', 'password': '1234'})
>>> response.status_code
200
>>> response = c.get('/user/protected-page/')
>>> response.content
b'<!DOCTYPE html...

Django - session key of actuall logged user, not possible to get from request

How to get the session_key in form Class? It is not possible to get the request parameter to do something like this : request.user
I've got this situation, and I need to pass to function get_user session_key which is also
not possible to retrieve from request.
class CustomEntryAdminForm(EntryAdminForm):
def get_user(session_key):
session = Session.objects.get(session_key=session_key)
uid = session.get_decoded().get('_auth_user_id')
user = User.objects.get(pk=uid)
return user
categories = MPTTModelMultipleChoiceField(
label=_('Categories'), required=False,
queryset=Category.objects.filter(groups__in=get_user('uwry5olhemchxnmwa36v10zt2bg9zeci').groups.all()),
widget=MPTTFilteredSelectMultiple(_('categories'), False,
attrs={'rows': '10'}))
Use pass user as keyword argument to your form. You do not need to jump through hoops and load active session key from request and then load user from decoded session. All you need to do is:
in view:
myform = MyFormClass(user= request.user)
in form:
class MyFormClass(forms.Form):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(MyFormClass, self).__init__(*args, **kwargs)
self.fields['categories'].queryset = Category.objects.filter(groups__in = self.user.groups.all())
NB! not complete working code. I just wanted to show you how you can use the self.user in queryset.

Categories

Resources