#python #django-models #django-rest-framework
#python #django-модели #django-rest-framework
Вопрос:
Я новичок в Django. Я пытаюсь создать зарегистрированного пользователя с созданным профилем по умолчанию. Но я получаю имя пользователя, уже существующее исключение
{
"owner": {
"username": [
"A user with that username already exists."
]
}
}
Требование заключается в том, что у пользователя может быть несколько профилей, и при регистрации нового пользователя нам нужно создать пользователя и связать профиль с этим пользователем. В следующий раз, если пользователь захочет создать новый профиль, пользователь захочет отправить только данные профиля. Текущий пользователь будет извлечен из объекта запроса.
Вот как выглядят мои модели :
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.
Есть ли у кого-нибудь идеи, как я могу передать объект user в profile_serializer, чтобы я мог использовать тот же метод create в следующий раз, когда пользователь захочет создать новый профиль?
Ответ №1:
Измените что-то подобное в своем 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()
return instance
else:
raise serializers.ValidationError("User Already Exists!")
Комментарии:
1. получение ошибки TypeError: User() получил неожиданный аргумент ключевого слова ‘password2’ ошибка
2. Все еще возникает та же проблема. Кстати, я могу это решить. Мне нужно удалить ‘UniqueValidator’ из поля имени пользователя.
3. похоже, у вашего
User
нет поля с именемpassword2