I am creating a simple registration/login app in Django Rest Framework using Rest APIs with Django Rest Knox's authentication, in which, upon registration, user will also upload a CSV File (which is an optional field).
I have a Person
Model which is an extended (derived or OneToOne
) Model of User
Model and has FileField
for the file to be uploaded.
I have two ModelSerializer
s, one is based on User
Model named MainRegisterSerializer
and serializes username
, email
and password
fields, and the other is based on Person
Model named RegisterSerializer
, which serializes FileField
and register
field (that is initialized with MainRegisterSerializer
class's constructor.
Now, in views.py
, I am accessing the RegisterSerializer
, to get the data from front that which includes username
, email
and password
fields from User
Model, and FileField
from Person
Model.
But, when I enter data in front-end and upload the file, and click on POST
button, I get the following error:
KeyError at /api/v1/register
'username'
on the code line user = User.objects.create_user(validated_data['username'], validated_data['email'], validated_data['password'], validated_data['file'])
in serializers.py
file.
My views.py
is:
from rest_framework.response import Response
from knox.models import AuthToken
from .serializers import RegisterSerializer
class RegisterAPI(generics.GenericAPIView):
serializer_class = RegisterSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
token = AuthToken.objects.create(user)
return Response({
"users": UserSerializer(user, context=self.get_serializer_context()).data,
"token": token[1]
})
My serializers.py
is:
from .models import Person
from django.contrib.auth.models import User
from rest_framework import serializers
class MainRegisterSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'email', 'password')
class RegisterSerializer(serializers.ModelSerializer):
register = MainRegisterSerializer()
class Meta:
model = Person
fields = ['register', 'file',]
optional_fields = ['file',]
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = User.objects.create_user(validated_data['username'], validated_data['email'], validated_data['password'], validated_data['file'])
return user
My models.py
is:
from django.db import models.
from django.contrib.auth.models import User
class Person(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
file = models.FileField(verbose_name="CSV File")
I have already worked around by trying various solutions told here on stackoverflow, but none of them worked for me, that's why I am posting the question. Any help will surely be appreciated. Thanks.
If you look at the validated data you can see, the data belonging to MainRegisterSerializer
serializer will be available with register
key. And data belonging to RegisterSerializer
serializer will be available with file
key.
validated data :
{'register': OrderedDict([('username', 'test'), ('email', 'test@gmail.com'), ('password', 'test123')]), 'file': <InMemoryUploadedFile: filename.txt (text/csv)>}
so to access any fields for register you need to use:
validated_data['register']['username'], validated_data['register']['email'] ..etc.
for accessing the file you can use : validated_data['file']