DRF: 将用户作为配置文件的密钥。

1 人关注

我是Django的新手。我正在尝试用默认的配置文件创建注册用户。但是我得到了用户名已经存在的异常

"owner": { "username": [ "A user with that username already exists."

要求是用户可以有多个配置文件,在注册新用户时,我们需要创建一个用户和一个与该用户相关的配置文件。下一次,如果用户想创建新的个人资料,用户只想发送个人资料数据。当前用户将被从请求对象中获取。

Here how my models look like :

from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
    name = models.CharField(max_length=255, null=False)
    birth_date = models.DateTimeField(auto_now=False, blank=True)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    def __str__(self):
        return "{} {}".format(self.name)

创建用户和配置文件的串行器如下所示

from django.contrib.auth import get_user_model
from rest_framework import serializers
from .models import Profile
from django.contrib.auth.models import User
User = get_user_model()
class UserCreateSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True, style={
                                     "input_type":   "password"})
    password2 = serializers.CharField(
        style={"input_type": "password"}, write_only=True, label="Confirm password")
    class Meta:
        model = User
        fields = [
            "username",
            "email",
            "password",
            "password2",
        extra_kwargs = {"password": {"write_only": True}}
    def create(self, validated_data):
        username = validated_data["username"]
        email = validated_data["email"]
        password = validated_data["password"]
        password2 = validated_data["password2"]
        first_name = validated_data["first_name"]
        last_name = validated_data["last_name"]
        if email and User.objects.filter(email=email).exclude(username=username).exists():
            raise serializers.ValidationError(
                {"email": "Email addresses must be unique."})
        if password != password2:
            raise serializers.ValidationError(
                {"password": "The two passwords differ."})
        user = User(username=username, email=email, first_name=first_name, last_name=last_name)
        user.set_password(password)
        user.save()
        return user
class ProfileSerializer(serializers.ModelSerializer):
    owner = UserCreateSerializer()
    class Meta:
        model = Profile
        fields = '__all__'
    def create(self, validated_data):
        user_data = validated_data.pop('owner')
        user = User.objects.get(username=user_data.username)
        profile = Profile.objects.create(owner=user, **validated_data)
        return profile

这是我对注册的看法

@swagger_auto_schema(methods=[ 'post'], request_body=ProfileSerializer)
@decorators.api_view(["POST"])
@decorators.permission_classes([permissions.AllowAny])
def registration(request):
    user_data = request.data['owner']
    serializer = UserCreateSerializer(data=user_data)
    if not serializer.is_valid():
        return response.Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
    user = serializer.save()
    profile_data = request.data
    profile_data.pop('owner')
    profile_data['owner'] = user_data
    profile_serializer = ProfileSerializer(data=profile_data, partial=True)
    if not profile_serializer.is_valid():
        return response.Response(profile_serializer.errors, status.HTTP_400_BAD_REQUEST)
    profile = profile_serializer.save()
    refresh = RefreshToken.for_user(profile.owner)
    res = {
        "refresh": str(refresh),
        "access": str(refresh.access_token),
    return response.Response(res, status.HTTP_201_CREATED)

在验证profile_data时,它给了我错误。

有谁知道我如何将用户对象传递给profile_serializer,以便下次用户想创建新的资料时,我可以使用同一个创建方法?

python
django-models
django-rest-framework
Dipesh Gandhi
Dipesh Gandhi
发布于 2020-08-26
1 个回答
satyajit
satyajit
发布于 2020-08-26
已采纳
0 人赞同

在你的 serializers.py 文件中做这样的修改。

from rest_framework import serializers
from django.contrib.auth import get_user_model
from django.db.models import Q
User = get_user_model()
class UserCreateSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(label='Email')
    username = serializers.CharField(label='Userame')
    password = serializers.CharField(write_only=True, required=True, style={
                                     "input_type": "password"})
    password2 = serializers.CharField(
        style={"input_type": "password"}, write_only=True, label="Confirm password")
    class Meta:
        model = User
        fields = [
            "username",
            "email",
            "password",
            "password2",
        extra_kwargs = {"password": {"write_only": True}}
    def create(self, data):
        username = data['username']
        email = data['email']
        password = data['password']
        password2 = data['password2']
        user_queryset = User.objects.filter(Q(email__iexact=email) | Q(username__iexact=username)).first()
        password = data.pop('password', None)
        instance = self.Meta.model(**data)
        if password != password2:
            raise serializers.ValidationError({"password": "The two passwords differ."})
        if user_queryset == None:
            if password is not None:
                instance.set_password(password)
            instance.save()