I have a Branch model with a foreign key to account (the owner of the branch):
class Branch(SafeDeleteModel):     _safedelete_policy = SOFT_DELETE_CASCADE     name = models.CharField(max_length=100)     account = models.ForeignKey(Account, null=True, on_delete=models.CASCADE)     location = models.TextField()     phone = models.CharField(max_length=20, blank=True,                          null=True, default=None)     create_at = models.DateTimeField(auto_now_add=True, null=True)     update_at = models.DateTimeField(auto_now=True, null=True)      def __str__(self):         return self.name      class Meta:         unique_together = (('name','account'),)      ...   I have a Account model with a foreign key to user (one to one field):
class Account(models.Model):     _safedelete_policy = SOFT_DELETE_CASCADE     name = models.CharField(max_length=100)     user = models.OneToOneField(User)     create_at = models.DateTimeField(auto_now_add=True)     update_at = models.DateTimeField(auto_now=True)      def __str__(self):         return self.name + ' - ' + self.create_at.strftime('%Y-%m-%d %H:%M:%S')   I've created a ModelViewSet for Branch which shows the branch owned by the logged in user:
class BranchViewSet(viewsets.ModelViewSet):     serializer_class = BranchSerializer     permission_classes = (permissions.IsAuthenticated,)       def get_queryset(self):         queryset = Branch.objects.all().filter(account=self.request.user.account)         return queryset   Now to create a new branch, I want to save account field with request.user.account, not with data sent from the rest client (for more security). for example:
def create(self, request, *args, **kwargs):     if request.user.user_type == User.ADMIN:         request.data['account'] = request.user.account         return super(BranchViewSet, self).create(request, *args, **kwargs)  def perform_create(self, serializer):     '''         Associate branch with account     '''     serializer.save(account=self.request.user.account)   In branch serializer
class BranchSerializer(serializers.ModelSerializer):     account = serializers.CharField(source='account.id', read_only=True)      class Meta:         model = Branch         fields = ('id', 'name', 'branch_alias',               'location', 'phone', 'account')         validators = [             UniqueTogetherValidator(                 queryset=Branch.objects.all(),                 fields=('name', 'account')             )         ]   but I got this error: This QueryDict instance is immutable. (means request.data is a immutable QueryDict and can't be changed)
Do you know any better way to add additional fields when creating an object with django rest framework?
The QuerySet is immutable - chaining methods to our queryset doesn't modify the original queryset - it creates a new one.
class QueryDict. In an HttpRequest object, the GET and POST attributes are instances of django.http.QueryDict , a dictionary-like class customized to deal with multiple values for the same key. This is necessary because some HTML form elements, notably <select multiple> , pass multiple values for the same key.
As you can see in the Django documentation:
The QueryDicts at request.POST and request.GET will be immutable when accessed in a normal request/response cycle.
so you can use the recommendation from the same documentation:
To get a mutable version you need to use QueryDict.copy()
or ... use a little trick, for example, if you need to keep a reference to an object for some reason or leave the object the same:
# remember old state _mutable = data._mutable  # set to mutable data._mutable = True  # сhange the values you want data['param_name'] = 'new value'  # set mutable flag back data._mutable = _mutable   where data it is your QueryDicts
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With