Django: запрос реляционных моделей в сериализаторе - PullRequest
0 голосов
/ 16 апреля 2020

У меня есть модель проекта и членства, где у каждого проекта есть список участников. Мне нужно выяснить, есть ли текущий зарегистрированный пользователь в списке участников проекта из сериализатора проекта, но мне кажется, что я не могу получить правильный запрос в моем методе get_i_am_member. Мне нужно передать идентификатор проекта из модели проекта в модель членства, чтобы отфильтровать данные, а затем проверить, соответствует ли пользователь в модели отфильтрованного членства пользователю, выполняющему запрос. Может кто-нибудь, пожалуйста, помогите? Вот мой код:

######################################################
# 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'))

1 Ответ

0 голосов
/ 16 апреля 2020

По умолчанию 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})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...