'str' object has no attribute 'get' django rest framework - django

I'm trying to connect rest framework views to a template, the get method is working properly but when posting datas it gives me the error :
views.py:
class Login(APIView):
serializer_class = LoginSerializer
permission_classes = [IsAnonymous, ]
template_name = 'accounts/login.html'
renderer_classes = [TemplateHTMLRenderer]
style = {'template_pack': 'rest_framework/vertical/'}
def get(self, request):
serializer = self.serializer_class()
return Response({'serializer': serializer, 'style': self.style})
def post(self, request):
payload = request.data
serializer = self.serializer_class(data=payload)
if serializer.is_valid():
user = authenticate(request,
username=payload['username'],
password=payload['password']
)
if user:
login(request, user)
response = {
'message': 'you logged in successfully!'
}
code = status.HTTP_200_OK
else:
response = {
'message': 'your username or password is wrong!'
}
code = status.HTTP_401_UNAUTHORIZED
else:
response = {
'error': serializer.errors
}
code = status.HTTP_403_FORBIDDEN
return Response(data=response, status=code)
I don't know where am I doing wrong , I appreciate if anyone can help me in this case

Related

How can I define Model ViewSet for contact form that sends email in django-rest-framework?

I have a APIView for a contact that takes input data from user and send it to mail:
from django.core.mail import send_mail
class ContactView(APIView):
serializer_class = ContactSerializer
def post(self, request, *args, **kwargs):
serializer_class = ContactSerializer(data = request.data)
if serializer_class.is_valid():
data = serializer_class.validated_data
name = data.get('name')
email = data.get('email')
message = data.get('message')
send_mail('Contact Form Mail from ' + name, message, email, ['bibekjoshi34#gmail.com'],)
return Response({"success":"sent"}, status=status.HTTP_200_OK)
else:
return Response({"error":"failed"}, status=status.HTTP_400_BAD_REQUEST)
urls.py
urlpatterns = [
path('contactapi', views.ContactView.as_view()),
]
Question:
How can I do it using DRF ModelViewset? This below code isn't working.
class CustomerContactViewSet(viewsets.ModelViewSet):
permission_classes = [AllowAny]
queryset = Contact.objects.all()
http_method_names = ['post']
serializer_class = ContactSerializer
def post(self, request):
serializer_class = ContactSerializer(data=request.data)
if serializer_class.is_valid():
data = serializer_class.validated_data
full_name = data.get('full_name')
email = data.get('email')
phone_no = data.get('phone_no')
message = data.get('message')
send_mail('Mail From' + full_name, phone_no, message, email, ['bibekjoshi34#gmail.com'],)
return Response({"success":"sent"}, status=status.HTTP_200_OK)
else:
return Response({"error":"failed"}, status=status.HTTP_400_BAD_REQUEST)
What is the best way to make contact-form: that stores data in database as well as sends to the admin mail: --------> For Production Level?

Return response statement is not returning any response

I am creating a logout view to logout from my django restframework using simplejwt. There is no direct way to logout so only blacklisting the refresh token is the workarround.
Those print statements works expectedly so it does blacklist the tokens but the return statement doesn't return anything, why is that and how may I return a Response?I am guessing the save function doesnt return anything, is it ture?
class LogoutSerializer(serializers.Serializer):
refresh = serializers.CharField()
def validate(self, attrs):
self.token = attrs['refresh']
return attrs
def save(self, **kwargs):
try:
RefreshToken(self.token).blacklist()
print('done')
return Response({'msg':'token has been blacklisted'})
except TokenError:
print('not done')
return Response({'msg':'token is expired or blacklisted'})
views.py
class LogoutAPIView(APIView):
serializer_class = LogoutSerializer
permission_classes = [IsAuthenticated]
def post(self, request):
serializer = self.serializer_class(data = request.data)
serializer.is_valid(raise_exception = True)
serializer.save()
return Response(status = status.HTTP_204_NO_CONTENT)
def post(self, request):
serializer = self.serializer_class(data = request.data)
serializer.is_valid(raise_exception = True)
serializer.save()
return Response(status = status.HTTP_204_NO_CONTENT) # this is the response that you're actually returning to the client.
If you want to return the responses in the serializer you can do:
class LogoutSerializer(serializers.Serializer):
refresh = serializers.CharField()
def validate(self, attrs):
self.token = attrs['refresh']
return attrs
def save(self, **kwargs):
RefreshToken(self.token).blacklist()
then:
def post(self, request):
serializer = self.serializer_class(data = request.data)
serializer.is_valid(raise_exception = True)
try:
serializer.save()
return Response({'msg':'token has been blacklisted'})
except TokenError:
return Response({'msg':'token is expired or blacklisted'})

I want to force change password on first login Django Rest

I have a custom User model with field is_resetpwd as a boolean field with default value True
I want that to change to False when the password is changed, following is my password change view
class ChangePasswordView(APIView):
"""
An endpoint for changing password.
"""
serializer_class = ChangePasswordSerializer
model = User
permission_classes = (IsAuthenticated,)
def get_object(self, queryset=None):
obj = self.request.user
# print("obj", obj)
return obj
def post(self, request, *args, **kwargs):
self.object = self.get_object()
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
# Check old password
if not self.object.check_password(serializer.data.get("old_password")):
return Response({"old_password": ["Wrong password."]}, status=status.HTTP_400_BAD_REQUEST)
# set_password also hashes the password that the user will get
self.object.set_password(serializer.data.get("new_password"))
self.object.save()
response = {
'message': 'Password updated successfully',
}
return Response(response)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
what should I add in this to change my boolean value
Just before save() add this
self.object.is_resetpwd = False
and then save the objects just like before
The updated code will look like this
"""
An endpoint for changing passwords.
"""
serializer_class = ChangePasswordSerializer
model = User
permission_classes = (IsAuthenticated,)
def get_object(self, queryset=None):
obj = self.request.user
# print("obj", obj)
return obj
def post(self, request, *args, **kwargs):
self.object = self.get_object()
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
# Check old password
if not self.object.check_password(serializer.data.get("old_password")):
return Response({"old_password": ["Wrong password."]}, status=status.HTTP_400_BAD_REQUEST)
# set_password also hashes the password that the user will get
self.object.set_password(serializer.data.get("new_password"))
self.object.is_resetpwd = False
self.object.save()
response = {
'message': 'Password updated successfully',
}
return Response(response)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Signing in a user through django restframework (Android)

I am new to django rest-framework, but I am able create basic apis . But I wanted to know how can I log in a user from Android.
Should I create a api view which takes post data (username,password) and then tries the login method and return if user is successfully logged in or not?
How should I proceed ?
Thanks.
first, you should serialize your user class
class UserLoginSerializer(ModelSerializer):
token = CharField(read_only=True)
phone_number = IntegerField(required=False)
class Meta:
model = User
fields = [
# 'id',
'phone_number',
'password',
'token'
]
extra_kwargs = {
'password': {
'write_only': True
}
}
def validate(self, data):
phone_number = data['phone_number']
password = data['password']
if not phone_number:
raise ValidationError('Phone number is required to login.')
user = User.objects.get(phone_number=phone_number)
if not user:
raise ValidationError('Your account does not exist.')
elif not user.check_password(password):
raise ValidationError('Incorrect password, please try again.')
return data
then, you should create your login view class
class UserLoginAPIView(CreateAPIView):
serializer_class = UserLoginSerializer
queryset = User.objects.all().filter(is_active=True)
def post(self, request, *args, **kwargs):
serializer = UserLoginSerializer(data=request.data)
user = User.objects.all()
try:
user =
user.get(Q(phone_number__iexact=request.data['phone_number']))
except:
return Response({'error': 'user does not exist.'}, status=status.HTTP_404_NOT_FOUND)
if serializer.is_valid(raise_exception=True):
# serializer.save()
return Response({'id': user.id}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_404_NOT_FOUND)
after doing this two thing you need to add your view class to a URL
url(r'^login/$', UserLoginAPIView.as_view(), name='user-login')

django facebook and user password authentication

i am new in django, i require login with user and password or facebook, i am using rest framework for api endpoints. ¿How i can do it?
i try with:
django-rest-framework-social-oauth2 but don't work for my because i needs save additional info from user after first enter.
I expect have 2 endpoint one sending user and password and another sending facebook auth token
Here's sample code for user login for Django Rest Framework:
class Login(APIView):
#csrf_exempt
def dispatch(self, *args, **kwargs):
return super(Login, self).dispatch(*args, **kwargs)
#staticmethod
def post(request):
request_data = JSONParser().parse(request)
if 'email' in request_data and 'password' in request_data:
try:
validate_email(request_data['email'])
except ValidationError:
return JsonResponse({'result': 'E-mail is invalid'}, status=400)
user = authenticate(email=request_data['email'], password=request_data['password'])
if user is not None:
if user.is_active:
try:
token = Token.objects.get(user=user)
except Token.DoesNotExist:
token = Token.objects.create(user=user)
return JsonResponse({'result': 'success', 'token': token.key, 'id': user.id}, status=200)
return JsonResponse({'result': 'E-mail or password is incorrect'}, status=400)
return JsonResponse({'result': 'E-mail or password is empty'}, status=400)
Here's sample for FB login code for Django Rest Framework (from my test project):
class FbLogin(APIView):
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.AllowAny,)
#csrf_exempt
def dispatch(self, *args, **kwargs):
return super(FbLogin, self).dispatch(*args, **kwargs)
#staticmethod
def post(request):
request_data = JSONParser().parse(request)
if 'access_token' in request_data:
response = requests.get(
url='https://graph.facebook.com/v2.5/me/',
params={
'access_token': request_data['access_token'],
'fields': 'email,first_name,last_name',
},
)
json_response = json.loads(response.text)
if 'error' not in json_response:
response_photo = requests.get(
url='https://graph.facebook.com/v2.5/%s/picture' % json_response['id'],
params={
'redirect': 'false',
'type': 'large',
},
)
response_photo_json = json.loads(response_photo.text)
response_friends = requests.get(
url='https://graph.facebook.com/v2.5/me/friends/',
params={
'access_token': request_data['access_token'],
'limit': 300,
},
)
generated_password = get_random_string(10, '0123456789abcdefghijklmnopqrstuvwxyz')
try:
json_response_email = json_response['email']
except:
first_name = json_response['first_name'].lower()
last_name = json_response['last_name'].lower()
id = json_response['id']
json_response_email = first_name + last_name + id + '#facebook.com'
try:
current_user = User.objects.get(email=json_response_email)
current_user.set_password(generated_password)
current_user.save()
except User.DoesNotExist:
new_user = User.objects.create_user(email=json_response_email,
password=generated_password)
new_user.provider_id = json_response['id']
new_user.provider_type = 'facebook'
if 'first_name' in json_response:
new_user.first_name = json_response['first_name']
if 'last_name' in json_response:
new_user.last_name = json_response['last_name']
new_user.save()
photo_name = urlparse(response_photo_json['data']['url']).path.split('/')[-1].split('?')[-1]
photo_content = urllib.request.urlretrieve(response_photo_json['data']['url'])
new_user.profile_photo.save(photo_name, File(open(photo_content[0], 'rb')), save=True)
user = authenticate(email=json_response_email, password=generated_password)
try:
token = Token.objects.get(user=user)
except Token.DoesNotExist:
token = Token.objects.create(user=user)
if user is not None:
if user.is_active:
fullname = json_response['first_name'] + ' ' + json_response['last_name']
return JsonResponse({'result': 'success', 'token': token.key, 'name': fullname}, status=200)
return JsonResponse({'result': 'User access token is incorrect'}, status=400)