Reputation: 115
I want to update a model without knowing which fields to update beforehand.
For example:
The request to my url api/user/(?P<pk>[0-9]+)/message-update/(?P<id>[0-9]+)/
will have a payload JSON with a POST request method like this:
{
"category": "personal",
"type_of_transaction": "paid"
}
The problem here is that the payload key-value pairs will keep changing depending upon the fields to be changed.
I have tried this but it seems to have no effect at all:
message = Message.objects.get(user=pk, id=id)
json_data = json.loads(request.body.decode(encoding='UTF-8'))
attributes_to_be_changed = json_data.keys()
values = json_data.values()
for i in attributes_to_be_changed:
message.i = values[attributes_to_be_changed.index(i)]
message.save(update_fields=attributes_to_be_changed)
try:
json_message = MessageSerializer(Message, many=False)
except Exception as e:
return JsonResponse({"error": e})
return JsonResponse(json_message.data, safe=False)
I have a message model as below:
user = models.ForeignKey(User, related_name='messages')
sender = models.CharField(max_length=15, blank=True)
body = models.CharField(max_length=400, blank=True)
account = models.ForeignKey(Account, blank=True, null=True)
card = models.ForeignKey(CreditCard, blank=True, null=True)
type_of_transaction = models.CharField(max_length=10)
message_date = models.DateTimeField(blank=True, null=True)
category = models.CharField(max_length=15, blank=True)
spent_at = models.CharField(max_length=15, blank=True)
meta = models.CharField(max_length=30, blank=True)
amount = models.FloatField()
lat = models.CharField(max_length=50, default="null")
lon = models.CharField(max_length=50, default="null")
def __str__(self):
try:
state = "Message from "+self.account.name+" for "+self.user.username
except Exception:
state = "Message from "+ self.card.card_number+"for"+self.user.username
return state
My serializer:
class MessageSerializer(serializers.ModelSerializer):
account = serializers.SerializerMethodField()
def get_account(self, obj):
try:
name = obj.account.name
except Exception:
name = obj.card.card_number
return name
class Meta:
model = Message
fields = ('id','sender','body','account','category','spent_at','meta','type_of_transaction', 'amount', 'message_date')
Upvotes: 0
Views: 1002
Reputation: 1524
You can do the following:
# Note: if id field is primary key, you don´t need to consult by user also
message_updated = Message.objects.filter(user=pk, id=id).update(**json_data)
Upvotes: 0
Reputation: 115
Got it!
It was a typo in json_message = MessageSerializer(Message, many=False)
.
Replaced Message
with message
and got it working.
It was previously taking the model as an argument.
Upvotes: 0
Reputation: 1187
Well, I think in your case you should use setattr
for key, value in json_data.items():
setattr(message, key, value)
Or maybe update_or_create could be a good idea, too https://docs.djangoproject.com/en/2.0/ref/models/querysets/#update-or-create
defaults is your json_data
Upvotes: 1