码迷,mamicode.com
首页 > 其他好文 > 详细

django restframework PrimaryKeyRelatedField筛选的困惑

时间:2018-10-10 23:58:21      阅读:394      评论:0      收藏:0      [点我收藏+]

标签:manage   null   date   添加   简单   选择   load   output   lse   

一.在开发某运动app时,遇见以下情况

  1.部分表内容如下:

class Sports(models.Model):
    ‘‘‘
    运动表
    ‘‘‘
    school = models.ForeignKey(Schools, verbose_name=‘学校‘, on_delete=models.CASCADE)
    sport_name = models.CharField(max_length=30, verbose_name=运动项目)
    image = models.ImageField(upload_to=sports/%Y/%m, verbose_name=运动封面图)
    add_time = models.DateTimeField(default=datetime.now, verbose_name=添加时间)

    class Meta:
        verbose_name = 运动项目
        verbose_name_plural = verbose_name
        unique_together = (school, sport_name)

    def __str__(self):
        return self.sport_name
class Schedule(models.Model):
    ‘‘‘
    发起约运动
    ‘‘‘
    Status = ((1, 已完成), (2, 待人加入), (3, 已取消))
    user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, verbose_name=发起人)
    join_type = models.BooleanField(verbose_name=是否发起人)
    now_people = models.IntegerField(verbose_name=已有人数, null=True, blank=True)
    school = models.ForeignKey(Schools, on_delete=models.CASCADE, verbose_name=‘学校‘, default=‘‘)
    sport = models.ForeignKey(Sports, on_delete=models.CASCADE, verbose_name=运动项目)
    address = models.CharField(verbose_name=约定地点, max_length=100)
    sport_time = models.DateTimeField(verbose_name=约定运动开始时间)
    sport_end_time = models.DateTimeField(verbose_name=约定运动结束时间, default=‘‘)
    people_nums = models.IntegerField(verbose_name=人数)
    add_time = models.DateTimeField(default=datetime.now, verbose_name=添加时间)
    status = models.IntegerField(choices=Status, verbose_name=状态)

    class Meta:
        verbose_name = 发起约运动
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.sport.sport_name + - + str(self.sport_time)
class UserProfile(AbstractUser):
    ‘‘‘
    用户表
    ‘‘‘
    name = models.CharField(max_length=30, null=True, blank=True, verbose_name=姓名)
    image = models.ImageField(upload_to=users/, default=‘‘, null=True, blank=True, verbose_name=头像)
    birthday = models.DateField(null=True, blank=True, verbose_name=出生年月)
    mobile = models.CharField(max_length=11, verbose_name=电话, null=True, blank=True)
    student_id = models.CharField(max_length=32, verbose_name=学号, default=‘‘, null=True, blank=True)
    gender = models.CharField(max_length=6, choices=((male, ), (fmale, )), default=, verbose_name=性别)
    email = models.EmailField(verbose_name=邮箱)
    school = models.ForeignKey(Schools, verbose_name=‘学校‘, on_delete=models.CASCADE)
    institude = models.ForeignKey(Schools, verbose_name=学院, on_delete=models.CASCADE, related_name=institude)
    profession = models.ForeignKey(Schools, verbose_name=专业, on_delete=models.CASCADE, related_name=profession)
    add_time = models.DateTimeField(default=datetime.now, verbose_name=添加时间)

    class Meta():
        verbose_name = 用户
        verbose_name_plural = verbose_name

    def __str__(self):
        if self.name:
            return self.name
        else:
            return self.username

class Schedule(models.Model):
    ‘‘‘
    发起约运动
    ‘‘‘
    Status = ((1, 已完成), (2, 待人加入), (3, 已取消))
    user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, verbose_name=发起人)
    join_type = models.BooleanField(verbose_name=是否发起人)
    now_people = models.IntegerField(verbose_name=已有人数, null=True, blank=True)
    school = models.ForeignKey(Schools, on_delete=models.CASCADE, verbose_name=学校, default=‘‘)
    sport = models.ForeignKey(Sports, on_delete=models.CASCADE, verbose_name=运动项目)
    address = models.CharField(verbose_name=约定地点, max_length=100)
    sport_time = models.DateTimeField(verbose_name=约定运动开始时间)
    sport_end_time = models.DateTimeField(verbose_name=约定运动结束时间, default=‘‘)
    people_nums = models.IntegerField(verbose_name=人数)
    add_time = models.DateTimeField(default=datetime.now, verbose_name=添加时间)
    status = models.IntegerField(choices=Status, verbose_name=状态)

    class Meta:
        verbose_name = 发起约运动
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.sport.sport_name + - + str(self.sport_time)

 

   2.序列化想实现的功能:

    在序列化Schedule表时,sport是一个外键字段,想筛选sport的外键school是当前已登录的用户的school字段下的该学校所有运动项目(即筛选为queryset=Sports.objects.filter(school=user.school)),看似很简单,但该如何在字段中获取当前用户呐。

    首先想到,把该字段设计为SerializerMethodField字段,即如下(该方法确实能实现筛选,但这不是我要的结果,我想在序列化时有该字段,并且能选择筛选出的数据中的一个并添加新的数据):

#失败方法
sport = serializers.SerializerMethodField() def get_sport(self, obj): all_sport = Sports.objects.filter(school=self.context[request].user.school).values_list(pk,flat=True) json_all = SportsSerializer(all_sport, many=True, context={request: self.context[request]}).data return all_sport

 

    然后就有点麻烦,想从写view中的get_queryset(),也是只能在list或retrieve中才能筛选,而序列化添加仍是一个问题;又想到从写一个类或者函数专门筛选,但是又增大了获取当前用户的难度,有点恼火,咋办,看看源码它写了哪些方法,真看不太懂,只能了解一点。

    看到了RelatedField中的get_queryset()方法,好像重写它有点作用:

 def get_queryset(self):
        queryset = self.queryset
        if isinstance(queryset, (QuerySet, Manager)):
            # Ensure queryset is re-evaluated whenever used.
            # Note that actually a `Manager` class may also be used as the
            # queryset argument. This occurs on ModelSerializer fields,
            # as it allows us to generate a more expressive ‘repr‘ output
            # for the field.
            # Eg: ‘MyRelationship(queryset=ExampleModel.objects.all())‘
            queryset = queryset.all()
        return queryset

三.目前最终方案: 

    于是勉强写吧,重写该方法确实有用,只能说功能完成了,但还真得改进:

 class SportPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
        def get_queryset(self):
            queryset = self.queryset
            # if isinstance(queryset, (QuerySet, Manager)):
            # Ensure queryset is re-evaluated whenever used.
            # Note that actually a `Manager` class may also be used as the
            # queryset argument. This occurs on ModelSerializer fields,
            # as it allows us to generate a more expressive ‘repr‘ output
            # for the field.
            # Eg: ‘MyRelationship(queryset=ExampleModel.objects.all())‘
            queryset = queryset.filter(school=self.context[request].user.school)
            return queryset

    sport = SportPrimaryKeyRelatedField(queryset=Sports.objects.all(), label="运动")

 

    

django restframework PrimaryKeyRelatedField筛选的困惑

标签:manage   null   date   添加   简单   选择   load   output   lse   

原文地址:https://www.cnblogs.com/lyq-biu/p/9769421.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!