问题描述
我正在使用带有 Django-graphene GraphQL API 和 postgres 数据库的 Angular UI。
目前我已经实现了一个功能,通过为每个表添加一个“searchField”并在每次创建和更新该表中的项目时更新它来到达全局搜索字段。并且使用 graphql 过滤器,每次用户进行全局搜索时,我都会为查询过滤 hte searchField。我对 Django 很陌生,所以我不确定这是否是解决此问题的有效方法,但这就是我所拥有的:-
创建变异
class createuser(graphene.Mutation):
class Arguments:
input = UserInput(required=True)
ok = graphene.Boolean()
user = graphene.Field(UserType)
@staticmethod
def mutate(root,info,input=None):
ok = True
searchField = input.username if input.username is not None else "" + \
input.title if input.title is not None else "" + \
input.bio if input.bio is not None else ""
user_instance = User(user_id=input.user_id,title=input.title,bio=input.bio,institution_id=input.institution_id,searchField=searchField)
user_instance.save()
return createuser(ok=ok,user=user_instance)
更新变异
class UpdateUser(graphene.Mutation):
class Arguments:
id = graphene.Int(required=True)
input = UserInput(required=True)
ok = graphene.Boolean()
user = graphene.Field(UserType)
@staticmethod
def mutate(root,id,input=None):
ok = False
user = User.objects.get(pk=id)
user_instance = user
if user_instance:
ok = True
user_instance.name = input.name if input.name is not None else user.name
user_instance.avatar = input.avatar if input.avatar is not None else user.avatar
user_instance.institution_id = input.institution_id if input.institution_id is not None else user.institution_id
user_instance.title = input.title if input.title is not None else user.title
user_instance.bio = input.bio if input.bio is not None else user.bio
user_instance.searchField = user_instance.searchField + \
user_instance.name if user_instance.name is not None else ""
user_instance.searchField = user_instance.searchField + \
user_instance.title if user_instance.title is not None else ""
user_instance.searchField = user_instance.searchField + \
user_instance.bio if user_instance.bio is not None else ""
user_instance.save()
return UpdateUser(ok=ok,user=user_instance)
return UpdateUser(ok=ok,user=None)
不确定您是否能分辨出来,但我对 Python 和 Django 非常陌生。我在这里所做的是,每次创建或更新用户记录时,我都会在名为 searchField
的表中维护一个字段,该字段将包含我想要全局的表中所有字段的字符串搜索触及。我已经像这样手动编写了每一行。不确定这是否符合最佳实践。
这是用户模型。
用户模型
class User(AbstractUser):
name = models.CharField(max_length=50)
email = models.EmailField(blank=False,max_length=255,unique=True)
avatar = models.CharField(max_length=250,blank=True,null=True)
institution = models.ForeignKey(
'Institution',on_delete=models.PROTECT,null=True)
title = models.CharField(max_length=150,null=True)
bio = models.CharField(max_length=300,null=True)
searchField = models.CharField(max_length=600,null=True)
USERNAME_FIELD = 'username'
EMAIL_FIELD = 'email'
这里有几件事。
- 首先,我知道我在更新突变解析器方法中设置 searchField 的更新方面做错了。这是由于我对 Python 的了解不足。因此,如果有人能找出我做错了什么,那就太好了。
- 我完全自己做这件事,我不知道这种方法在效率方面是否真的是一个很好的策略,或者是否已经有一个基于 graphql 的 django api 的好的解决方案。所以如果有的话,请指点我。
谢谢。
解决方法
是的,如果您想更新您的 searchField,您必须从头开始构建它。如果您使用旧数据并附加新数据,如果您搜索旧数据,它将返回记录,这是您想要避免的。
关于您的第二个问题,您可以使用 django-filter
。
步骤:
-
安装
django-filter
-
创建一个基本过滤器集类并向其添加
search
字段class CustomFilterSet(filters.FilterSet): search = filters.CharFilter(method='search_filter') def search_filter(self,queryset,field_name,value): return queryset
-
为从自定义过滤器集类继承的模型创建过滤器集类并覆盖
search_filter
方法。为了对查询集执行or
操作,请使用Q
对象。在你的情况下是这样的:class UserFilterSet(CustomFilterSet): ... def search_filter(self,value): return queryset.filter( Q(username__icontains=value) | Q(title__icontains=vallue) | Q(bio__icontains=value) )
查找指定字段中的值,而不管 小写/大写
-
创建 graphql 类型并将相关的 filterset_class 添加到 Meta 类:
class UserType(DjangoObjectType): class Meta: model = User filterset_class = UserFilterSet interfaces = (relay.Node,)
现在您只需传递一个字符串即可全局搜索指定字段。