16

私は Django-rest-framework を使用して API を開発し、それを Web アプリから使用しています。django.auth User モデルの Fk を持つ Physician Model があります。フォームから Physician Model に投稿したいのですが、シリアライザーから次のメッセージが返されます。

{"user":{"non_field_errors":["無効なデータです。辞書が必要ですが、Unicode を取得しました。"]}}

ユーザー オブジェクトの主キーを送信しています。外部キーを DRF に格納する正しい方法 (または 1 つの方法) はどれですか。シリアライザーで get_validation_exclusions をオーバーライドし、ビューセットで perform_create メソッドをオーバーライドしようとしました。

API と Web アプリは切り離されています。API は django で開発され、Web アプリは angularjs で開発されています。

私のモデル

class Physician(models.Model):
    medical_office_number = models.CharField(max_length = 15)
    fiscal_id_number = models.CharField(max_length = 20)
    user = models.OneToOneField(User)

    def __unicode__(self):
        return self.user.first_name +' '+ self.user.last_name

シリアライザー:

class PhysicianSerializer(serializers.ModelSerializer):
    user = AccountSerializer()
    class Meta:
        model = Physician
        fields = ('id', 'user', 'medical_office_number', 'fiscal_id_number')
        read_only_fields = ('id')
        depth = 1
    def get_validation_exclusions(self, *args, **kwargs):
        exclusions = super(PhysicianSerializer, self).get_validation_exclusions()
        return exclusions + ['user']

*編集これは私のアカウントのシリアライザーで、この実装に基づいており、@Kevin Brown の提案があります

class PrimaryKeyNestedMixin(serializers.RelatedField, serializers.ModelSerializer):

    def to_internal_value(self, data):
        return serializers.PrimaryKeyRelatedField.to_internal_value(self, data)
    def to_representation(self, data):
        return serializers.ModelSerializer.to_representation(self, data)

class AccountSerializer(PrimaryKeyNestedMixin):
    password = serializers.CharField(write_only=True, required=False)
    confirm_password = serializers.CharField(write_only=True, required=False)

    class Meta:
        model = Account
        fields = ('id', 'email', 'username', 'created_at', 'updated_at',
                  'first_name', 'last_name', 'password',
                  'confirm_password', 'is_admin',)
        read_only_fields = ('created_at', 'updated_at',)

ビューセット

class AccountViewSet(viewsets.ModelViewSet):
    lookup_field = 'username'
    queryset = Account.objects.all()
    serializer_class = AccountSerializer

このオブジェクトをシリアライズしようとすると、エラーが発生します。

したがって、要素から任意のユーザーを投稿できます<select>。しかし、解決策を確認できません。私が欠けているものはありますか?

エラースタックトレース

TypeError at /api/v1/accounts/

__init__() takes exactly 1 argument (5 given)

Exception Location:     /home/jlromeroc/workspace/asclepios/venv/local/lib/python2.7/site-packages/rest_framework/relations.py in many_init, line 68
Python Executable:  /home/jlromeroc/workspace/asclepios/venv/bin/python
Python Version:     2.7.3

File "/home/jlromeroc/workspace/asclepios/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response 111. response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/home/jlromeroc/workspace/asclepios/venv/local/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view 57. return view_func(*args, **kwargs)
File "/home/jlromeroc/workspace/asclepios/venv/local/lib/python2.7/site-packages/rest_framework/viewsets.py" in view 85. return self.dispatch(request, *args, **kwargs)
File "/home/jlromeroc/workspace/asclepios/venv/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch 407. response = self.handle_exception(exc) File "/home/jlromeroc/workspace/asclepios/venv/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch 404. response = handler(request, *args, **kwargs)
File "/home/jlromeroc/workspace/asclepios/venv/local/lib/python2.7/site-packages/rest_framework/mixins.py" in list 45. serializer = self.get_serializer(instance, many=True)
File "/home/jlromeroc/workspace/asclepios/venv/local/lib/python2.7/site-packages/rest_framework/generics.py" in get_serializer 90. instance, data=data, many=many, partial=partial, context=context File "/home/jlromeroc/workspace/asclepios/venv/local/lib/python2.7/site-packages/rest_framework/relations.py" in __new__ 48. return cls.many_init(*args, **kwargs)
File "/home/jlromeroc/workspace/asclepios/venv/local/lib/python2.7/site-packages/rest_framework/relations.py" in many_init 68. list_kwargs = {'child_relation': cls(*args, **kwargs)}

Exception Type: TypeError at /api/v1/accounts/
Exception Value: __init__() takes exactly 1 argument (5 given)

編集**ビューセットの作成関数をオーバーライドし、オブジェクトをリクエストに含めることを選択したため、検証できますが、シリアライザーは Account モデルの新しいオブジェクトを挿入しようとします。どうすればこの動作を防ぐことができますか? PhysicianSerializer クラスのシリアライザーを read_only に設定しようとしましたが、django はモデルを null の user_id で保存しようとしました。関連オブジェクトを挿入せずにモデルを保存するにはどうすればよいですか?

4

5 に答える 5

0

Integer の ForeignKey を使用したデータ保存リクエストの問題と、ネストされたデータを使用してデータを読み取るリクエストの問題を解決しようとするフィールド タイプを作成しました。

これはクラスです:

class NestedRelatedField(serializers.PrimaryKeyRelatedField):
"""
    Model identical to PrimaryKeyRelatedField but its
    representation will be nested and its input will
    be a primary key.
"""

def __init__(self, **kwargs):
    self.pk_field = kwargs.pop('pk_field', None)
    self.model = kwargs.pop('model', None)
    self.serializer_class = kwargs.pop('serializer_class', None)
    super().__init__(**kwargs)

def to_representation(self, data):
    pk = super(NestedRelatedField, self).to_representation(data)
    try:
        return self.serializer_class(self.model.objects.get(pk=pk)).data
    except self.model.DoesNotExist:
        return None

def to_internal_value(self, data):
    return serializers.PrimaryKeyRelatedField.to_internal_value(self, data)

したがって、次のように使用されます。

class PostModelSerializer(serializers.ModelSerializer):

    message = NestedRelatedField(
         queryset=MessagePrefix.objects.all(),
         model=MessagePrefix,
         serializer_class=MessagePrefixModelSerializer
   )

これがお役に立てば幸いです。

于 2019-10-22T12:01:43.607 に答える