代码之家  ›  专栏  ›  技术社区  ›  coder

为什么在使用users_data=validate_data.pop(users,[])时,我在Django中得到的是电子邮件,而不是用户的ID?

  •  0
  • coder  · 技术社区  · 1 年前

    我正在处理一个Django项目,遇到了一个与在序列化程序中提取用户数据有关的问题 create 方法

    在代码中, users_data 包含用户的电子邮件地址,但我需要使用用户的ID将用户与任务关联起来。但是,当我更换 User.objects.get(email=user_data) 具有 User.objects.get(id=user_data) ,我遇到一个错误。如何修改序列化程序 创造 如何正确地将用户与其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
    
    1 回复  |  直到 1 年前
        1
  •  1
  •   Vegard    1 年前

    DRF正在反序列化您的 user_data 转换为实际的用户对象。这意味着您可以更改为:

            for user_data in users_data:
                user = User.objects.get(id=user_data.id)
    
    推荐文章