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