I am trying to get rid of the explicit binding between my models. Thus, instead of ForeignKey , I use IntegerField to simply save the primary key of the target model as a field. This way I will handle the relationship manually at the code level. This is because I will have to move some schemas to different database instances. Therefore, they cannot have a connection.
Now I am facing a problem with my nested serializer. I am trying to instantiate a model below:
17 class Customer(models.Model): 18 id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) 19 phone_no = models.CharField(max_length=15, unique=True)
And this is my CustomerAddress model that references the Customer model:
47 class CustomerAddress(models.Model): 48
Following are my serializers:
7 class CustomerAddressSerializer(serializers.ModelSerializer): 8 9 class Meta: 10 model = CustomerAddress 11 depth = 1 31 class CustomerSerializer(serializers.ModelSerializer): 32 cust_addresses = CustomerAddressSerializer(many=True) 33 34 class Meta: 35 model = Customer 36 depth = 1 37 fields = ('id', 'phone_no', 'cust_addresses',) 38 39 def create(self, validated_data): 40 cust = Customer.objects.create(id=uuid.uuid4()) 41 42 for addr in validated_data['cust_addresses']: 43 address = addr['address'] 44 cust_addr = CustomerAddress.objects.create(address=address, customer_id=cust.id) 45 46 return cust
My views:
12 class CustomerView(generics.RetrieveAPIView, generics.CreateAPIView): 13 serializer_class = CustomerSerializer 14 22 def get_object(self): 23 session = self.request.session 24 if session.has_key('uuid'): 25 id = session['uuid'] 26 cust = Customer.objects.get(pk=uuid.UUID(id)) 27 return cust 28 return None
When I try to run the send request above, from my test:
71 def test_create_customer_address(self): 72 cust_url = reverse('user_v1:customer') 73 # Now we create a customer, and use it UID in the "customer" data of /cust-address/ 74 cust_data = {"first_name": "Rohit", "last_name": "Jain", "phone_no": "xxxxxx", "email_id": " test@gmail.com ", "cust_addresses": [{"city_id": 1, "address": "addr", "pin_code": "123124", "address_tag": "XYZ"}]} 75 cust_response = self.client.post(cust_url, cust_data, format='json') 76 print 'Post Customer' 77 print cust_response 78 self.assertEqual(cust_response.data['id'], str(cust_id))
My test does not work with the following error:
====================================================================== ERROR: test_create_customer_address (app.tests.CustomerViewTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/ubuntu/src/django-proj/app/tests.py", line 75, in test_create_customer_address cust_response = self.client.post(cust_url, cust_data, format='json') File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/test.py", line 168, in post path, data=data, format=format, content_type=content_type, **extra) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/test.py", line 90, in post return self.generic('POST', path, data, content_type, **extra) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/compat.py", line 231, in generic return self.request(**r) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/test.py", line 157, in request return super(APIClient, self).request(**kwargs) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/test.py", line 109, in request request = super(APIRequestFactory, self).request(**kwargs) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/django/test/client.py", line 466, in request six.reraise(*exc_info) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view return view_func(*args, **kwargs) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/django/views/generic/base.py", line 71, in view return self.dispatch(request, *args, **kwargs) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/views.py", line 456, in dispatch response = self.handle_exception(exc) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/views.py", line 453, in dispatch response = handler(request, *args, **kwargs) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/generics.py", line 190, in post return self.create(request, *args, **kwargs) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/mixins.py", line 21, in create headers = self.get_success_headers(serializer.data) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 470, in data ret = super(Serializer, self).data File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 217, in data self._data = self.to_representation(self.instance) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 430, in to_representation attribute = field.get_attribute(instance) File "/home/ubuntu/Envs/rj-venv/local/lib/python2.7/site-packages/rest_framework/fields.py", line 317, in get_attribute raise type(exc)(msg) AttributeError: Got AttributeError when attempting to get a value for field `cust_addresses` on serializer `CustomerSerializer`. The serializer field might be named incorrectly and not match any attribute or key on the `Customer` instance. Original exception text was: 'Customer' object has no attribute 'cust_addresses'. ----------------------------------------------------------------------
All this worked fine when I had a CustomerAddress binding on ForeignKey on Customer . I donβt understand how to fix this. I tried to look at the source code to make sure that some tweaking was needed. But I'm at a loss. I feel that I need to somehow configure my serializer, maybe override the to_representation method, but I'm not sure.
BTW, an error occurs only when creating an instance of the model. For a GET request, I get the correct json with a nested serializer.
Has anyone else tried to do something similar and succeeded? What needs to be done to make this work? And yes, I have to remove the explicit foreign key binding.