使用Graphene+Django时,如何实现反向前缀匹配查询ContentType?
解决方案
针对你需要通过带"Node"后缀的类名,反向查询对应model字段值的Django ContentType的需求,提供以下几种可行的QuerySet实现方式:
方法一:直接截取目标字符串(简单场景)
如果确定类名后缀是严格的"Node"(大小写完全一致),可以直接截取目标字符串的前缀部分,再查询:
from django.contrib.contenttypes.models import ContentType target_class = "MyModelNode" model_name = target_class[:-4] # 提取出"MyModel" # 精确匹配model字段 content_type = ContentType.objects.get(model=model_name)
如果需要忽略大小写匹配,替换为:
content_type = ContentType.objects.get(model__iexact=model_name)
方法二:数据库层面字符串拼接(灵活匹配)
如果要处理后缀大小写不固定的情况(比如"node"、"NODE"),可以用Django的数据库函数实现不区分大小写的拼接匹配:
from django.db.models import Value from django.db.models.functions import Concat, Lower from django.contrib.contenttypes.models import ContentType target_class = "MyModelNode" target_lower = target_class.lower() # 将model字段与"node"拼接后转小写,和目标字符串的小写版本对比 content_type = ContentType.objects.get( Lower(Concat('model', Value('node'))) == target_lower )
这种方式直接在数据库层面处理字符串,避免了本地字符串处理可能带来的大小写问题。
方法三:正则表达式查询(复杂场景)
如果需要适配更复杂的后缀变体,可以使用不区分大小写的正则匹配:
from django.contrib.contenttypes.models import ContentType import re target_class = "MyModelNode" # 匹配目标字符串末尾的任意大小写"Node",提取前缀作为model名 pattern = re.compile(r'^(.*)node$', re.IGNORECASE) match_result = pattern.match(target_class) if match_result: model_name = match_result.group(1) content_type = ContentType.objects.get(model__iexact=model_name)
注意事项
- 建议使用
filter()替代get()并检查返回结果数量,避免因匹配不到或匹配多个结果抛出异常。 - 根据实际业务场景选择最适合的匹配方式,优先使用方法一或方法二,性能优于正则查询。
内容的提问来源于stack exchange,提问作者Scott Deerwester
相关产品推荐
相关产品推荐

