Reputation: 1241
I have a form-data which I want to insert into two different models. So at first I created both the models as shown below -
This is the model User.
class User(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField(max_length=255, blank=False)
last_name = models.CharField(max_length=255, blank=False)
email = models.EmailField(max_length=255, blank=False, unique= True)
phone_number = models.BigIntegerField(blank=False, unique= True)
password = models.TextField(blank=False)
company_name = models.CharField(max_length=255, blank=True)
is_active = models.BooleanField(default= True)
role = models.ForeignKey(Role, on_delete=models.CASCADE, blank=False)
business = models.ForeignKey(Businesses, on_delete=models.CASCADE, blank=True)
objects = UserManager()
USERNAME_FIELD = 'email'
def __str__(self):
return 'User Object ({})'.format(self.id)
This is the model DeliveryAgent.
class DeliveryAgentVehicle(models.Model):
vehicle_model = models.CharField(max_length=255, blank=False)
year_of_make = models.IntegerField(blank=False)
vehicle_photo = models.ImageField(upload_to='vehicle_photo/', max_length=None, null=True, blank=False)
driver_license = models.ImageField(upload_to='driver_license/', max_length=None, blank=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
def __str__(self):
return 'DeliveryAgentVehicle Object ({})'.format(self.id)
Then I created APIView called DeliveryAPIView().
In this view at first I have declared parser_classes. Then in post method I updated request.data dictionary by adding key as a role and id
(of role Delivery_agent
) as value. I did this so that this view would only create user of type Delivery_Agent
class DeliveryAPIView(APIView):
parser_classes = (FormParser, MultiPartParser)
def post(self, request, format=None):
request.data['role'] = Role.objects.get(role_name='Delivery_agent').id
deserialized_data = DeliverySerializer(data=request.data)
if deserialized_data.is_valid():
try:
delivery_agent = deserialized_data.save()
except IntegrityError as identifier:
return Response(identifier)
return Response({
"message":"Done"
})
As I want to store the form-data into two different model, I have splited validate_data
dictionary into two saperate dictionaries delivey_agent_vehicle
and delivery_agent
in serializer.
To map the vehicle details with the delivery agent I first need to have the user_id
of delivery agent. So to create delivery agent I had to pass dictionary delivey_agent
to create_user()
method which belongs to User
model's manager. Then expecting that it will create delivery agent and return a string representation instance of the delivery agent I called create()
method of DeliveryAgentVehicle
to insert the vehicle details of the delivery agent.
This is how my serializer look like -
class DeliverySerializer(serializers.Serializer):
email = serializers.EmailField(max_length=255, required=True)
password = serializers.CharField(max_length=255, required=True)
first_name = serializers.CharField(max_length=255, required=True)
last_name = serializers.CharField(max_length=255, required=True)
phone_number = serializers.IntegerField(required=True)
role = serializers.IntegerField(required=True)
vehicle_model = serializers.CharField(max_length=255, required=True)
year_of_make = serializers.CharField(max_length=255, required=True)
photo_of_vehicle = serializers.ImageField(max_length=None, allow_empty_file=False)
driver_license = serializers.ImageField(max_length=None, allow_empty_file=False)
def create(self, validated_data):
validated_data['role'] = Role.objects.get(pk=validated_data['role'])
delivey_agent={}
delivey_agent['email'] = validated_data['email']
delivey_agent['password'] = validated_data['password']
delivey_agent['first_name'] = validated_data['first_name']
delivey_agent['last_name'] = validated_data['last_name']
delivey_agent['phone_number'] = validated_data['phone_number']
delivey_agent['role'] = validated_data['role']
agent_id = User.objects.create_user(**delivey_agent)
delivey_agent_vehicle={}
delivey_agent_vehicle['vehicle_model'] = validated_data['vehicle_model']
delivey_agent_vehicle['vehicle_model'] = validated_data['year_of_make']
delivey_agent_vehicle['vehicle_model'] = validated_data[ 'photo_of_vehicle']
delivey_agent_vehicle['vehicle_model'] = validated_data['driver_license']
delivey_agent_vehicle['user'] = agent_id
agent_vehicle_id = DeliveryAgentVehicle.objects.create(**delivey_agent_vehicle)
print(delivey_agent_vehicle)
print(delivey_agent)
return agent_id
This is the error which it has returned -
Internal Server Error: /users/delivery/signup/
Traceback (most recent call last):
File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/django/core/handlers/base.py", line 145, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/django/core/handlers/base.py", line 143, in _get_response
response = response.render()
File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/django/template/response.py", line 105, in render
self.content = self.rendered_content
File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/rest_framework/response.py", line 70, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/rest_framework/renderers.py", line 103, in render
allow_nan=not self.strict, separators=separators
File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/rest_framework/utils/json.py", line 25, in dumps
return json.dumps(*args, **kwargs)
File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 238, in dumps
**kw).encode(obj)
File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "/Users/jeetpatel/Desktop/env/lib/python3.7/site-packages/rest_framework/utils/encoders.py", line 67, in default
return super().default(obj)
File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type IntegrityError is not JSON serializable
Upvotes: 1
Views: 73
Reputation: 6296
Your error is here:
try:
delivery_agent = deserialized_data.save()
except IntegrityError as identifier:
return Response(identifier)
Response expects a JSON serializable object to return to the user which is usually the serializer data, a dictionary. However, you're passing it the IntegrityError
object that you catch.
If you want to return the raw DB error message to the client(which is not advisable), you should do something like this instead:
try:
delivery_agent = deserialized_data.save()
except IntegrityError as identifier:
return Response({
"message":str(identifier)
}, status=400)
Upvotes: 1