I want to update the Model data using nested serializers via PATCH call in DRF.
I have custom User
Model, Country
, City
, Detail
Model.
I have MainUserSerializer
, CountrySerializer
, CitySerializer
and UserSerializer
, and I have UserAPI
view.
Below is my models.py
:
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=254, null=True, blank=True)
email = models.EmailField(max_length=254, unique=True)
first_name = models.CharField(max_length=254, null=True, blank=True)
last_name = models.CharField(max_length=254, null=True, blank=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % (self.pk)
class Country(models.Model):
name = models.CharField(max_length=100, default='c')
def __str__(self):
return ("{}".format(self.name))
class City(models.Model):
name = models.CharField(max_length=100 ,default='c')
country = models.ForeignKey(Country, on_delete=models.CASCADE)
def __str__(self):
return ("{} ({})".format(self.name, self.country.name))
class Detail(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
gender = models.CharField(max_length=20, default='g')
age = models.IntegerField(default=0)
country = models.IntegerField(default=1)
city = models.IntegerField(default=1)
def __str__(self):
return ("{} ({} {})".format(self.user.email, self.user.first_name, self.user.last_name))
my serializers.py
:
class MainUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'first_name', 'last_name', 'email')
class CitySerializer(serializers.ModelSerializer):
class Meta:
model = City
fields = ('name',)
class CountrySerializer(serializers.ModelSerializer):
city = CitySerializer()
class Meta:
model = Country
fields = ('name', 'city')
class UserSerializer(serializers.ModelSerializer):
usr = MainUserSerializer()
country = CountrySerializer()
city = CitySerializer()
class Meta:
model = Detail
fields = ('usr', 'gender', 'age', 'country', 'city')
def update(self, instance, validated_data):
instance = super().update(instance, validated_data)
instance.save()
return instance
and my views.py
is:
class UserAPI(generics.GenericAPIView):
permission_classes = [AllowAny]
serializer_class = UserSerializer
def get(self, request, id):
detail = Detail.objects.get(user=User.objects.get(pk=id))
usr = User.objects.get(pk=id)
data = {
'id': usr.id,
'username': usr.username,
'first_name': usr.first_name,
'last_name': usr.last_name,
'email': usr.email,
'gender': detail.gender,
'age': detail.age,
'country': detail.country,
'city': detail.city
}
return Response(data)
def patch(self, request, id):
usr = User.objects.get(pk=id)
detail = Detail.objects.get(user=usr)
serializer = self.get_serializer(detail, data=request.data, partial=True)
print(request.POST)
if serializer.is_valid():
serializer.save()
print("SUCCESS")
return Response(code=200)
return JsonResponse(data="wrong parameters", safe=False)
Error Details:
Error Name: AttributeError: 'NoneType' object has no attribute '_meta'
Full Error:
Traceback Switch to copy-and-paste view
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\exception.py, line 55, in inner
response = get_response(request) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\base.py, line 220, in _get_response
response = response.render() …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\response.py, line 114, in render
self.content = self.rendered_content …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\response.py, line 70, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\renderers.py, line 724, in render
context = self.get_context(data, accepted_media_type, renderer_context) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\renderers.py, line 657, in get_context
raw_data_patch_form = self.get_raw_data_form(data, view, 'PATCH', request) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\renderers.py, line 563, in get_raw_data_form
data = serializer.data.copy() …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\serializers.py, line 555, in data
ret = super().data …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\serializers.py, line 257, in data
self._data = self.get_initial() …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\serializers.py, line 403, in get_initial
return OrderedDict([ …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\serializers.py, line 404, in <listcomp>
(field.field_name, field.get_initial()) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\serializers.py, line 405, in get_initial
for field in self.fields.values() …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\utils\functional.py, line 49, in __get__
res = instance.__dict__[self.name] = self.func(instance) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\serializers.py, line 356, in fields
for key, value in self.get_fields().items(): …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\serializers.py, line 1051, in get_fields
info = model_meta.get_field_info(model) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\utils\model_meta.py, line 39, in get_field_info
forward_relations = _get_forward_relationships(opts) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\utils\model_meta.py, line 96, in _get_forward_relationships
not field.remote_field.through._meta.auto_created …
Local vars
Anyone please guide me why I am getting this error.
You wrote
usr
instead ofuser
in your serializer: