web-dev-qa-db-ja.com

このQueryDictインスタンスは不変です

アカウントへの外部キー(ブランチの所有者)を持つブランチモデルがあります。

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'),)

    ...

ユーザーへの外部キーを持つアカウントモデルがあります(1対1のフィールド)。

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')

ログインしたユーザーが所有するブランチを表示するブランチのModelViewSetを作成しました。

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

次に、新しいブランチを作成するために、残りのクライアントから送信されたデータではなく、request.user.accountでアカウントフィールドを保存します(セキュリティを強化するため)。例えば:

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)

ブランチシリアライザー

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')
            )
        ]

しかし、私はこのエラーを受け取りました:このQueryDictインスタンスは不変です。 (request.dataは不変のQueryDictであり、変更できないことを意味します)

Django RESTフレームワークでオブジェクトを作成するときにフィールドを追加するためのより良い方法を知っていますか?

8

Djangoのドキュメント で確認できるように:

QueryDicts at request.POST and request.GETは、 通常のリクエスト/レスポンスサイクル

そのため、同じドキュメントの推奨事項を使用できます。

変更可能なバージョンを取得するには、 QueryDict.copy()を使用する必要があります

または...たとえば、何らかの理由でオブジェクトへの参照を維持するためにを維持する必要がある場合、またはオブジェクトを同じままにする場合は、少しトリックを使用します。

# 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

データはここにあります QueryDicts

Django RESTフレームワークでオブジェクトを作成するときにフィールドを追加するためのより良い方法を知っていますか?

オブジェクトを作成/更新するときに追加のデータを提供する公式な方法は、次に示すようにそれらをserializer.save()に渡すことです here

1
Linovia

https://docs.djangoproject.com/en/2.0/ref/request-response/#querydict-objects

通常の要求/応答サイクルでアクセスされた場合、request.POSTおよびrequest.GETでのQueryDictsは不変です。変更可能なバージョンを取得するには、QueryDict.copy()を使用する必要があります。

0
kevin wong