Django Rest Framework:SerializerMethodField和get_queryset

时间:2018-11-21 13:49:07

标签: django rest api django-rest-framework

在我的数据库中,我有两个表-usersuser_properties

我需要使用GET参数phone过滤输出。但是,这两个表都具有列phone并具有不同的值。

当我执行GET请求时(例如“?phone = 123456789”),我不仅需要使用user_properties.phone,而且还要使用user.phone通过电话号码搜索用户!

我用Google搜索并找到了一种使用get_queryset(filtering)和SerializerMethodField(修改输出)来部分实现此目的的方法:

models.py

class User(models.Model):
    balance = models.DecimalField(decimal_places=35, max_digits=40)
    fio = models.CharField(max_length=64)
    phone = models.CharField(max_length=64, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'user'


class UserProperties(models.Model):
    user_id = models.IntegerField(primary_key=True)
    phone = models.CharField(max_length=11)

    class Meta:
        managed = False
        db_table = 'user_properties'

views.py

class UserPropertiesViewSet(viewsets.ModelViewSet):
queryset = UserProperties.objects.all()
serializer_class = serializers.UserPropertiesSerializer

def get_queryset(self):
    queryset = self.queryset
    # phone number from GET
    phone = self.request.query_params.get('phone')

    # Search users matches in user_properties using by phone number
    if phone:
        queryset = UserProperties.objects.all()
        users = queryset.filter(phone__contains=phone)
        return users
    else:
        return queryset

serializers.py

class UserPropertiesSerializer(serializers.ModelSerializer):
all_phones = serializers.SerializerMethodField()

class Meta:
    model = models.UserProperties
    fields = ['user_id', 'phone', 'fio', 'url', 'all_phones',]

# phone numbers from user and user_properties tables
def get_all_phones(self, obj):
    # search phones in <user> table by user_id
    user_phones = models.User.objects.filter(id__exact=obj.user_id).values_list('phone', flat=True)
    # add phones from user_properties table
    result = [obj.phone,]
    # add phones from user table
    for phone in user_phones[0].split(','):
        result.append(''.join(filter(lambda x: x.isdigit(), phone)))

    # return list with all phones
    return set(result)

然后我的过滤结果中出现all_phones列:

{
"count": 1,
"next": null,
"previous": null,
"results": [
    {
        "user_id": 17897,
        "phone": "123456789", <--- user_properties table
        "fio": "....",
        "url": "....",
        "all_phones": [
            "123456789",
            "5512222",
            "49543"
        ] <--- user_properties.phone + user.phone
    }
]

}

但是在get_queryset中,我仅使用user_properties表中的“真实” phone列进行过滤。如何使用“虚拟” all_phones列过滤结果?或在两个表格中搜索并获得拥有此电话号码之一的用户?有可能吗还是我的方法不正确?

谢谢!

1 个答案:

答案 0 :(得分:1)

这个问题更多的是关于Django ORM而不是Django REST框架,但是像这样重写get_queryset方法将在两个模型的phone字段中进行搜索:

from django.db.models import Q

...

def get_queryset(self):
    queryset = self.queryset
    # phone number from GET
    phone = self.request.query_params.get('phone')

    if phone:
        queryset = queryset.filter(
            Q(phone__contains=phone)
            | Q(user__phone__contains=phone)
        )

    return queryset
相关问题