I am having a problem setting up authentication in django rest. Everytime I try to create a user using a post request to this url http://127.0.0.1:8000/user/create/ I get this error: AssertionError: Expected a Response, HttpResponse or HttpStreamingResponse to be returned from the view, but received a <class 'NoneType'>
[09/Apr/2021 14:41:43] "POST /user/create/ HTTP/1.1" 500 82190. I have tried may solutions here with no success.
views.py
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework.views import APIView
from rest_framework import status, permissions
from rest_framework.response import Response
from .serializers import TokenObtainPairSerializer
from rest_framework.generics import CreateAPIView
from .serializers import CustomUserSerializer, MyTokenObtainPairSerializer
class CustomUserCreate(APIView):
permission_classes = (permissions.AllowAny,)
def post(self, request, format = 'json'):
serializer = CustomUserSerializer(data= request.data)
if serializer.is_valid():
user = serializer.save()
if user:
json = serializer.data
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializers.py
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework import serializers
from .models import CustomUser
class CustomUserSerializer(serializers.ModelSerializer):
email = serializers.EmailField(required=True)
username = serializers.CharField()
password = serializers.CharField(min_length = 8, write_only= True)
class Meta:
model = CustomUser
fields = ('email', 'username', 'password')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
password = validated_data.pop('password', None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
urls.py
from django.urls import path
from rest_framework_simplejwt import views as jwt_views
from .views import ObtainTokenPairWithColorView, CustomUserCreate, HelloWorld
urlpatterns = [
path('user/create/', CustomUserCreate.as_view(), name="create_user"),
]
Your view does not return anything when serializer.is_valid() returns False. In that case you need to produce a response as well. Likely this is due to bad indentation:
class CustomUserCreate(APIView):
permission_classes = (permissions.AllowAny,)
def post(self, request, format = 'json'):
serializer = CustomUserSerializer(data= request.data)
if serializer.is_valid():
user = serializer.save()
if user:
json = serializer.data
return Response(status=status.HTTP_201_CREATED)
# outside the body of the if clause
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Related
I am creating a project with Django Rest Framework and I ran into some problems and im not able to fix them.
So, I have a URL for post method and when I post there using postman, I get an error:
{
"detail": "JSON parse error - Expecting property name enclosed in double quotes: line 1 column 2 (char 1)"
}
This is the data im sending:
{username:"REQUAB", password:"REQUAB", emailId:"requab#gmail.com"}
And just to check if i had some problem in the serializer or the model, i did a normal get request and i got correct output.
my models.py:
from django.db import models
# Create your models here.
class User(models.Model):
emailId = models.EmailField(max_length=50)
username = models.CharField(max_length=20)
password = models.CharField(max_length=50)
recipes = models.IntegerField(default=0)
def __str__(self):
return self.username
my serializers.py:
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'emailId', 'password', 'recipes']
my urls.py:
from django.urls import path
from .views import UsersList, UsersDetail
urlpatterns = [
path('', UsersList.as_view()),
]
my views.py:
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from users.models import User
from .serializers import UserSerializer
# Create your views here.
class UsersList(APIView):
def get(self, request, format=None):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request):
print(request.data)
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Pls help me with this (Thanks, in advance).
The error is pretty clear, try to enclose the property names in double quotes or use JSON.stringify when sending it (using JS).
It allow me to pass in json format data to post for creating record after i make def create so that json format like [{data:data,data:data}] can post in. How should i do so that i can also make put request with multiple object in one request or using post method to update?
Below is views.py.
from django.shortcuts import render
from .models import ListForm
# Create your views here.
from rest_framework import viewsets
from .serializers import ListFormSerializer
from rest_framework import filters
import django_filters.rest_framework
from rest_framework.response import Response
from rest_framework import status, viewsets
class ListFormViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = ListForm.objects.all().order_by('group')
serializer_class = ListFormSerializer
filter_backends = (django_filters.rest_framework.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter,)
filterset_fields = ['group','key_description']
search_fields = ['group']
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data, many=isinstance(request.data,list))
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
# return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
Maybe you need something like this:
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.decorators import action
import json
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.none()
serializer_class = serializers.PostSerializer
#action(detail=False, methods=['post'])
def update_this(self, request):
try:
data = json.loads(request.data)
except:
try:
data = dict(request.data)
except:
data = request.data
# You can do everything you want here with data
return Response({'code': 0, 'desc': 'OK', 'more_data': {}})
I'm sending a request with POSTMAN to my server, and getting JSON with such function
__get_json__ it work well.
Here it is by the way.
def __get_json__(request):
try:
if request.method == 'POST':
data = request.body.decode('utf-8')
json_data = json.loads(data)
json_response("OK")
return json_data
else:
return error_response(406, "Request was not a json or POST type")
except ValueError:
return exception_error(500, "Server Issue")
and after here i'm returning in the function register_user
def register_user(request):
user_jsonify_data = __get_json__(request)
I wanna to store my data to different fields, for example i have such JSON
{
"name": "Tenders",
"id": "2135324123",
"set": "set"
}
How can i split it correctly?
pip install djangorestframework
add rest_framework to settings.INSTALLED_APPS
Example:
# models.py
from django.db import models
class User(models.Model):
id = models.CharField(max_length=30, primary_key=True)
name = models.CharField(max_length=30)
set = models.CharField(max_length=30)
# serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
# views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializers import UserSerializer
class RegisterView(APIView):
serializer_class = UserSerializer
def post(self, request, format=None):
serializer = self.serializer_class(request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
I am new to Django and am confused on handling post requests to my server. I want to accept post requests in this json format: {“username”:”john#doe.com”,”password”:”pass#word1”} and to reply with these json formated responses:
{“status”:”success”,”message”:”user_authed”} if the user and password combination is found
{“status”:”failure”,”message”:”user_not_found”} if the user and password combination is not found
This is my views.py code
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from . models import users
from . serializers import userSerializer
class userList(APIView):
def get(self, request):
user = users.objects.all()
serializer = userSerializer(user, many=True)
return Response(serializer.data)
def post(self, request):
serializer = userSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
I want to know how I can format the post function to accept requests in the format above and how to customize the reply as authenticated or not. Any help would be appreciated with this
What you are trying to accomplish is called authentication.
Please read https://www.django-rest-framework.org/api-guide/authentication/ in advance.
Then edit your question according to what you learn.
Hope to hear from you soon!
#serializers.py
from rest_framework import serializers
UserRequestSerializer(serializers.Serializer)
username = CharField(required=True, max_length=128)
password = CharField(required=True, max_length=128)
#views.py
from .serializers import *
UserCheckView(APIView):
def post(request, *args, **kwargs):
serializer = UserRequestSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
try:
user = User.objects.get(username=serializer.validated_data['username'])
if user.check_password(serializer.validated_data['password']:
return Response(data={“status”:”success”,”message”:”user_authed”},status=status.HTTP_200_OK)
return Response(data={“status”:”failure”,”message”:”password_did_not_match”}, status=status.HTTP_400_BAD_REQUEST)
except User.DoesNotExist:
return Response(data={“status”:”failure”,”message”:”user_not_found”}, status=status.HTTP_404_NOT_FOUND)
I am not sure how to add 2FA to my django project and DRF ?
I will eventually connect this DRF with react and redux as the frontend.
Here is my Django side:
Models:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
def __str__(self):
return self.username
My Django api serializer
# Login API
class LoginAPI(generics.GenericAPIView):
serializer_class = LoginSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
# Check token and send back what user is associated with that token
class UserAPI(generics.RetrieveAPIView):
permission_classes = [
permissions.IsAuthenticated,
]
serializer_class = UserSerializer
def get_object(self):
return self.request.user
My Django urls:
from django.urls import path, include
from knox import views as knox_views
from accounts.api.views import LoginAPI, UserAPI
urlpatterns = [
path('api/auth', include('knox.urls')),
path('api/auth/login', LoginAPI.as_view()),
path('api/auth/user', UserAPI.as_view()),
path('api/auth/logout', knox_views.LogoutView.as_view(), name='knox_logout'),
My django views:
from rest_framework import generics, permissions
from rest_framework.response import Response
from knox.models import AuthToken
from accounts.api.serializers import LoginSerializer, UserSerializer
# Login API
class LoginAPI(generics.GenericAPIView):
serializer_class = LoginSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data
return Response({
"user": UserSerializer(user, context=self.get_serializer_context()).data,
"token": AuthToken.objects.create(user)[1]
})
# Check token and send back what user is associated with that token
class UserAPI(generics.RetrieveAPIView):
permission_classes = [
permissions.IsAuthenticated,
]
serializer_class = UserSerializer
def get_object(self):
return self.request.user