97

Django REST フレームワークで REST API をコーディングしています。API は、ソーシャル モバイル アプリのバックエンドになります。チュートリアルに従った後、すべてのモデルをシリアル化できるようになり、新しいリソースを作成して更新できるようになりました。

認証に AuthToken を使用しています。

私の質問は:

リソースを取得したら/users、アプリ ユーザーが登録できるようにします。では、別のリソース/registerを用意するか、匿名ユーザーが/users新しいリソースに POST できるようにする方がよいでしょうか?

また、アクセス許可に関するいくつかのガイダンスは素晴らしいでしょう。

4

11 に答える 11

116

Django REST Framework 3は、シリアライザーのオーバーライドメソッドを許可します。create

from rest_framework import serializers
from django.contrib.auth import get_user_model # If used custom user model

UserModel = get_user_model()


class UserSerializer(serializers.ModelSerializer):

    password = serializers.CharField(write_only=True)

    def create(self, validated_data):

        user = UserModel.objects.create_user(
            username=validated_data['username'],
            password=validated_data['password'],
        )

        return user

    class Meta:
        model = UserModel
        # Tuple of serialized model fields (see link [2])
        fields = ( "id", "username", "password", )

継承されたクラスのシリアル化されたフィールドは、Django Rest Framework v3.5ModelSerializer以降で特許を取得して宣言する必要があります。Meta

ファイルapi.py :

from rest_framework import permissions
from rest_framework.generics import CreateAPIView
from django.contrib.auth import get_user_model # If used custom user model

from .serializers import UserSerializer


class CreateUserView(CreateAPIView):

    model = get_user_model()
    permission_classes = [
        permissions.AllowAny # Or anon users can't register
    ]
    serializer_class = UserSerializer
于 2015-04-01T12:41:25.210 に答える
53

シリアライザーはパスワードの表示/取得を想定していないため、登録を処理するための独自のカスタム ビューを作成しました。/users リソースとは別の URL にしました。

私のURL conf:

url(r'^users/register', 'myapp.views.create_auth'),

私の見解:

@api_view(['POST'])
def create_auth(request):
    serialized = UserSerializer(data=request.DATA)
    if serialized.is_valid():
        User.objects.create_user(
            serialized.init_data['email'],
            serialized.init_data['username'],
            serialized.init_data['password']
        )
        return Response(serialized.data, status=status.HTTP_201_CREATED)
    else:
        return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST)

私は間違っているかもしれませんが、認証されていないリクエストが必要なため、このビューのアクセス許可を制限する必要はないようです...

于 2013-07-19T15:12:13.023 に答える
48

DRF 3.x で動作する最も簡単なソリューション:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'email', 'first_name', 'last_name')
        write_only_fields = ('password',)
        read_only_fields = ('id',)

    def create(self, validated_data):
        user = User.objects.create(
            username=validated_data['username'],
            email=validated_data['email'],
            first_name=validated_data['first_name'],
            last_name=validated_data['last_name']
        )

        user.set_password(validated_data['password'])
        user.save()

        return user

他の変更は必要ありません。認証されていないユーザーが新しいユーザー オブジェクトを作成する権限を持っていることを確認してください。

write_only_fieldsパスワード(実際には、保存されているハッシュ)が表示されないようにしますが、上書きされcreateた方法では、パスワードがクリアテキストではなくハッシュとして保存されます。

于 2015-04-25T16:19:55.797 に答える
16

上記の@cpuryは、write_only_fieldsオプションの使用を提案しました。ただし、これはDRF 3.3.3では機能しませんでした

DRF 3.0 では、 ModelSerializerのwrite_only_fieldsオプションは PendingDeprecation に移動され、DRF 3.2では、より一般的な extra_kwargs に置き換えられました。

extra_kwargs = {'password': {'write_only': True}}

于 2016-04-27T22:34:14.643 に答える
10

これまでのすべての回答は、ユーザーを作成し、ユーザーのパスワードを更新します。これにより、2 つの DB 書き込みが発生します。余分な不要な DB 書き込みを避けるために、保存する前にユーザーのパスワードを設定します。

from rest_framework.serializers import ModelSerializer

class UserSerializer(ModelSerializer):

    class Meta:
        model = User

    def create(self, validated_data):
        user = User(**validated_data)
        # Hash the user's password.
        user.set_password(validated_data['password'])
        user.save()
        return user
于 2016-07-14T18:50:54.213 に答える
5

パーティーには少し遅れましたが、これ以上コードを書きたくない人の助けになるかもしれません。

superメソッドを使用してこれを実現できます。

class UserSerializer(serializers.ModelSerializer):

    password = serializers.CharField(
          write_only=True,
    )

    class Meta:
       model = User
       fields = ('password', 'username', 'first_name', 'last_name',)

    def create(self, validated_data):
        user = super(UserSerializer, self).create(validated_data)
        if 'password' in validated_data:
              user.set_password(validated_data['password'])
              user.save()
        return user
于 2016-01-23T08:41:12.090 に答える