django - Django Rest 框架:SerializerMethodField 和 get_queryset
问题描述
在我的数据库中,我有两个表 -users
和user_properties
我需要使用 GET 参数过滤输出phone
。但是这两个表都有列phone
并且具有不同的值。
当我执行 GET 请求(例如“?phone=123456789”)时,我不仅需要使用 user_properties.phone,还需要使用 user.phone 通过电话号码搜索用户!
我用谷歌搜索并找到了一种使用get_queryset(过滤)和SerializerMethodField(修改输出)的方法:
模型.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'
视图.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
序列化程序.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
列过滤结果?或者在两个表中搜索并获取拥有此电话号码之一的用户?有可能吗?还是我的方法不对?
谢谢!
解决方案
这个问题更多的是关于 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
推荐阅读
- node.js - 在不配置验证器的情况下无法设置未编译的验证规则
- c# - 将带有列表的对象从视图传递到控制器。列表不是映射/
- c - 使用 SIGCHLD 处理僵尸
- python - python中用于人脸识别的特征脸问题
- json - JSON 中的动态标签
- keyboard - USB 3 主机可以编程为 USB 3 外围设备(或 HID 键盘)吗?
- reactjs - 如果用户已经存在于数据库中,则使用 react redux express 进行注册验证
- python - 将具有相同键的新值添加到 Firestore firebase 中的现有文档而不覆盖
- python - Python UDP 请求挂起
- python - pip3 在安装任何东西时不起作用并抛出 pip 需要 TLS/SSL,ssl Python 不可用