I'm trying to update an already db-saved object once it has successfully sent a message. it calls the update() method of the serializer class in order to achieve this. This is the model that will have it's instance updated:
class SMSMessages(models.Model):
sms_number_to = models.CharField(max_length=14)
sms_content = models.CharField(max_length=160)
sending_user = models.ForeignKey("SMSUser", on_delete=models.PROTECT, related_name="user_that_sent")
sent_date = models.DateTimeField(auto_now=True)
delivery_status = models.BooleanField(default=False)
class Meta:
verbose_name_plural = "SMSMessages"
def __str__(self):
return str(self.sending_user)
This is the serializer class I'm using:
class SMSMessagesSerializer(serializers.ModelSerializer):
"""
A class for serializing the SMSMessages model's data. It sub-classes the
ModelSerializer class from serializer's module.
"""
class Meta:
model = SMSMessages
fields = '__all__'
def update(self, instance, validated_data):
"""
This method is used to update an instance of the SMSMessages's delivery_status attribute.
It get's the value for delivery_status from the input parameter, updates the specific instance
of the SMSMessagesSerializer, saves that instance and returns it.
"""
instance = self.get_object()
instance.delivery_status = validated_data.get('delivery_status', instance.delivery_status)
instance.save()
return instance
and this is the APIView class that has the POST method that will update the if the message is successfully sent:
class SMSView(APIView):
"""
This class is responsible for all the method operations of an sms. It provides implementations for the GET, POST, and OPTIONS methods.
Each method provides it's own description.
"""
serializer_class = SMSMessagesSerializer
def get(self, request):
"""
This method is used to GET all created instance of the SMSMessages class that are saved in the db.
"""
queryset = SMSMessages.objects.filter(sending_user=request.user)
while queryset:
return Response(
data={
queryset.values()
},
status=status.HTTP_200_OK,
content_type="application/json"
)
else:
return Response(
data={
"no sms has been sent"
},
status=status.HTTP_404_NOT_FOUND,
content_type="application/json"
)
def post(self, request):
"""
This method is used to create an instance of the SMSMessages indirectly by using the SMSMessagesSerializer.
If that is valid it will be passed to the sender() method from the notification.sender module. The serializer
will be saved, aka the object will be saved to the database, and then the sender() is called. It will run three
times before it gives up and fails. Once that returns a True value the instance will be called, aka the object
will be saved to the database, with a delivery_status value of True.
"""
sms_messages_serializer = SMSMessagesSerializer(
data={
"sms_number_to": request.data.get("sms_number_to"),
"sms_content": request.data.get("sms_content"),
"sending_user": request.data.get("sending_user")
}
)
permission_classes = (permissions.IsAuthenticated)
if sms_messages_serializer.is_valid():
data_to_send = {
"number": sms_messages_serializer.validated_data[
"sms_number_to"
],
"msg_text": sms_messages_serializer.validated_data[
"sms_content"
]
}
sms_messages_serializer.save()
# TODO refactor this into it's own function
max_retry = 0
resp = Response()
while max_retry < 3:
max_retry += 1
status_flag, status_response = sender(data_to_send)
if not status_flag:
resp = Response(
data={
"error": f"{status_response.text}"
},
status=status_response.status_code,
content_type="application/json"
)
else:
sms_messages_serializer.update(
data={
"delivery_status": True
},
partial=True
)
resp = Response(
data={
"success": f"{status_response.json()}"
},
headers=status_response.headers,
status=status_response.status_code,
content_type="application/json"
)
return resp
else:
resp = Response(
data={
"error": "unable to send sms"
},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
content_type="application/json"
)
return resp
It will be accessed via the following urlpattern:
urlpatterns = [
path('sendsms/', SMSView.as_view(), name="send_sms"),
path('viewsms/', SMSView.as_view(), name="view_sms"),
]
But instead of successfully updating the instance using python
sms_messages_serializer.update(data={"delivery_status": True}partial=True) it throws TypeError: serializer.update() got an unexpected keyword argument 'data'.
I've tried to change the update in the SMSMessagesSerializer class to no avail and tried renameing the data attribute to validated_data or value but still it doesn't work. I need it to update the delivery_status to True once it sends the sms, how can I be able to do that?