我正在开发一个 Django 项目,遇到了与在序列化器的
create
方法中提取用户数据相关的问题。
在代码中,
users_data
包含用户的电子邮件地址,但我需要使用用户的 ID 将用户与任务关联起来。但是,当我将 User.objects.get(email=user_data)
替换为 User.objects.get(id=user_data)
时,我遇到了错误。如何修改序列化程序的 create
方法以正确地将用户与其 ID 而不是电子邮件相关联?
任何见解或建议将不胜感激。谢谢!
这是我的代码片段。
有效负载:
{
"id": null,
"title": "Task Title",
"description": "Task Description",
"due_to": "2024-06-28T22:00:00.000Z",
"created": null,
"updated": null,
"priority": "LOW",
"category": "TECHNICAL_TASK",
"status": "TO_DO",
"subtasks": [
{
"task_id": null,
"description": "Subtask 1",
"is_done": false
}
],
"users": [
1
]
}
class BaseTaskSerializer(serializers.ModelSerializer):
"""Serializes a task object"""
subtasks = SubtaskSerializer(many=True, required=False)
class Meta:
model = Task
fields = ['id', 'title', 'description', 'due_to', 'created', 'updated', 'priority', 'category', 'status',
'subtasks', 'users']
read_only_fields = ['created', 'updated']
def create(self, validated_data):
#print('self: ', self)
users_data = validated_data.pop('users', [])
subtasks_data = validated_data.pop('subtasks', [])
task = Task.objects.create(**validated_data)
print(users_data)
#print('validated_data', validated_data)
#print('users_data', users_data)
for user_data in users_data:
#print(user_data)
#print('users_dataaa: ', users_data)
#user = User.objects.get(id=user_data)
user = User.objects.get(email=user_data)
task.users.add(user)
for subtask_data in subtasks_data:
subtask_data['task_id'] = task.id
SubtaskSerializer().create(validated_data=subtask_data)
return task
class WriteTaskSerializer(BaseTaskSerializer):
users = serializers.PrimaryKeyRelatedField(queryset=User.objects.all().order_by('id'), many=True)
class ReadTaskSerializer(BaseTaskSerializer):
users = UserSerializer(many=True, required=False)
class Task(models.Model):
class Priority(models.TextChoices):
LOW = "LOW"
MEDIUM = "MEDIUM"
URGENT = "URGENT"
class Category(models.TextChoices):
TECHNICAL_TASK = "TECHNICAL_TASK"
USER_STORY = "USER_STORY"
class TaskStatus(models.TextChoices):
TO_DO = "TO_DO"
AWAIT_FEEDBACK = "AWAIT_FEEDBACK"
IN_PROGRESS = "IN_PROGRESS"
DONE = "DONE"
id = models.AutoField(primary_key=True)
title = models.TextField()
description = models.TextField(blank=True, null=True)
due_to = models.DateTimeField()
created = models.DateTimeField()
updated = models.DateTimeField(auto_now_add=True)
priority = models.TextField(choices=Priority.choices)
category = models.TextField(choices=Category.choices)
status = models.TextField(choices=TaskStatus.choices)
users = models.ManyToManyField(User, related_name='tasks')
def save(self, *args, **kwargs):
if not self.id:
self.created = timezone.now()
super().save(*args, **kwargs)
def __str__(self):
return f"{self.title}"
class UserManager(BaseUserManager):
"""Manager for user"""
def create_user(self, email, name, password=None, **extra_fields):
"""Create, save and return a new user."""
if not email:
raise ValueError('User must have an email address.')
user = self.model(email=self.normalize_email(email), name=name, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, name, password):
"""Create and save a new superuser with given details"""
user = self.create_user(email, name, password)
user.is_superuser = True
user.is_staff = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
"""Database model for users in the system"""
id = models.AutoField(primary_key=True)
email = models.EmailField(unique=True)
name = models.CharField(max_length=50)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
phone_number = models.CharField(max_length=20, blank=True, null=True)
avatar_color = models.CharField(max_length=7)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def save(self, *args, **kwargs):
if not self.pk:
self.avatar_color = random.choice([
'#FF5733', '#C70039', '#900C3F', '#581845',
'#8E44AD', '#1F618D', '#008000', '#A52A2A', '#000080'
])
super().save(*args, **kwargs)
def get_full_name(self):
"""Retrieve full name for user"""
return self.name
def __str__(self):
"""Return string representation of user"""
return self.email
class UserSerializer(serializers.ModelSerializer):
"""Serializer for the user object."""
class Meta:
model = get_user_model()
fields = ['id', 'email', 'password', 'name', 'phone_number', 'avatar_color']
extra_kwargs = {
'email': {'required': False},
'password': {'required': False, 'write_only': True, 'style': {'input_type': 'password'}, 'min_length': 6},
'name': {'required': False},
'phone_number': {'required': False},
'avatar_color': {'read_only': True}
}
def create(self, validated_data):
"""Create and return a user with encrypted password."""
return get_user_model().objects.create_user(**validated_data)
def update(self, instance, validated_data):
"""Update and return user."""
password = validated_data.pop('password', None)
user = super().update(instance, validated_data)
if password:
user.set_password(password)
user.save()
return user
class AuthTokenSerializer(serializers.Serializer):
"""Serializer for the user auth token."""
email = serializers.EmailField()
password = serializers.CharField(
style={'input_type': 'password'},
trim_whitespace=False,
)
def validate(self, attrs):
"""Validate and authenticate the user."""
email = attrs.get('email')
password = attrs.get('password')
user = authenticate(
request=self.context.get('request'),
username=email,
password=password,
)
if not user:
msg = _('Unable to authenticate with provided credentials.')
raise serializers.ValidationError(msg, code='authorization')
attrs['user'] = user
return attrs
DRF 正在将您的
user_data
反序列化为实际的用户对象。这意味着您可以更改为:
for user_data in users_data:
user = User.objects.get(id=user_data.id)