【问题标题】:Django: Query relational models in serializerDjango:在序列化程序中查询关系模型
【发布时间】:2020-07-30 04:32:23
【问题描述】:

我有一个项目和成员资格模型,其中每个项目都有一个成员列表。我需要确定当前登录的用户是否在项目序列化程序中列为项目成员,但我似乎无法在我的 get_i_am_member 方法中获得正确的请求。我需要将 Project 模型中的项目 ID 传递给 Membership 模型以过滤数据,然后检查过滤后的成员资格模型中的用户是否与发出请求的用户匹配。有人可以帮忙吗?这是我的代码:

######################################################
# Serializer
######################################################

class ProjectSerializer(LightWeightSerializer):
    id = Field()
    name = Field()
    slug = Field()
    description = Field()
    created_date = Field()
    modified_date = Field()
    owner = MethodField()
    members = MethodField()
    is_private = Field()
    anon_permissions = Field()
    public_permissions = Field()
    is_looking_for_people = Field()
    looking_for_people_note = Field()
    i_am_member = MethodField()
    i_am_admin = MethodField()
    my_permissions = MethodField()

    def get_members(self, project):
        members = Membership.objects.filter(project_id=project.id).select_related()
        return MembershipSerializer(members, many=True, context=self.context).data

    def get_i_am_member(self, request):
        members_list = Membership.objects.filter(project_id=request.project.id).select_related('user')
        for member in members_list:
            if member.user == request.username:
                print(member.user)
                print("True")
                return True
            else:
                print(member.user)
                print("False")
            return False
######################################################
# Models
######################################################
class Project(models.Model):
    name = models.CharField(max_length=250, null=False, blank=False,
                            verbose_name=_("name"))
    slug = models.SlugField(max_length=250, unique=True, null=False, blank=True,
                            verbose_name=_("slug"))
    description = models.TextField(null=False, blank=False,
                                   verbose_name=_("description"))

    logo = models.FileField(upload_to=get_project_logo_file_path,
                            max_length=500, null=True, blank=True,
                            verbose_name=_("logo"))

    created_date = models.DateTimeField(null=False, blank=False,
                                        verbose_name=_("created date"),
                                        default=timezone.now)
    modified_date = models.DateTimeField(null=False, blank=False,
                                         verbose_name=_("modified date"))
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True,
                              related_name="owned_projects", verbose_name=_("owner"), on_delete=models.CASCADE)

    members = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="projects",
                                     through="Membership", verbose_name=_("members"),
                                     through_fields=("project", "user"))

    is_private = models.BooleanField(default=True, null=False, blank=True,
                                     verbose_name=_("is private"))
    anon_permissions = ChoiceArrayField(
        models.TextField(null=False, blank=False, choices=ANON_PERMISSIONS),
        null=True,
        blank=True,
        default=list,
        verbose_name=_("anonymous permissions")
    )
    public_permissions = ChoiceArrayField(models.TextField(null=False, blank=False, choices=MEMBERS_PERMISSIONS),
                                    null=True, blank=True, default=list, verbose_name=_("user permissions"))

    is_featured = models.BooleanField(default=False, null=False, blank=True,
                                      verbose_name=_("is featured"))

    class Meta:
        db_table = "projects"
        verbose_name = "project"
        verbose_name_plural = "projects"
        ordering = ["name", "id"]
        index_together = [
            ["name", "id"],
        ]


class Membership(models.Model):
    # This model stores all project memberships. Also
    # stores invitations to memberships that do not have
    # assigned user.

    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, default=None,
                             related_name="memberships", on_delete=models.CASCADE)
    project = models.ForeignKey(Project, null=False, blank=False,
                                related_name="memberships", on_delete=models.CASCADE)
    role = models.ForeignKey('core.Role', null=False, blank=False,
                             related_name="memberships", on_delete=models.CASCADE)
    is_admin = models.BooleanField(default=False, null=False, blank=False)

    user_order = models.BigIntegerField(default=timestamp_ms, null=False, blank=False,
                                        verbose_name=_("user order"))

    class Meta:
        db_table = "memberships"
        verbose_name = "membership"
        verbose_name_plural = "memberships"
        unique_together = ("user", "project",)
        ordering = ["project", "user__full_name", "user__username", "user__email"]

    def get_related_people(self):
        related_people = get_user_model().objects.filter(id=self.user.id)
        return related_people

    def clean(self):
        # TODO: Review and do it more robust
        memberships = Membership.objects.filter(user=self.user, project=self.project)
        if self.user and memberships.count() > 0 and memberships[0].id != self.id:
            raise ValidationError(_('The user is already member of the project'))

【问题讨论】:

    标签: python django python-3.x serialization request


    【解决方案1】:

    默认情况下drf使用上下文传递请求对象,所以修改应该是:

    def get_i_am_member(self, project):
        members_list = Membership.objects.filter(project_id=project.id).select_related('user')
        for member in members_list:
            if member.user == self.context['request'].user:
                print(member.user)
                print("True")
                return True
            else:
                print(member.user)
                print("False")
            return False
    

    但万一你手动调用序列化器,你需要传递它:

    ProjectSerializer(instance=project, context={'request': request})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-14
      • 2014-02-15
      • 2016-09-17
      • 2016-12-18
      • 2016-07-28
      • 1970-01-01
      • 2017-02-13
      • 1970-01-01
      相关资源
      最近更新 更多