自定义 Django 模型字段的字段查找功能
我有一个自定义模型字段 YearWithSurenessField
,它在 python 中由自定义数据类型 YearWithSureness
表示。 YearWithSureness
的构造函数为 YearWithSureness(year='', is_certain=False)
,其中 year
为 ''
或四位数年份(作为字符串),并且 is_certain
是一个布尔值,表示我是否确定给定年份是正确的。这种类型的模型字段以year/is_certain的形式存储在我的数据库中,例如“2008/True”、“2011/False”、“/False”等。
例如,在Member
模型,我有一个字段 grad_year = YearWithSurenessField(...)
,它存储会员的毕业年份以及我是否确定我存储的年份是正确的。
我希望能够做的是使用类似的方法
Member.objects.filter(grad_year__year=2011)
来获取 grad_year 为“2011/True”或“2011/False”的所有成员的 QuerySet
。同样,我希望能够使用类似的方法
Member.objects.filter(grad_year__range=(2000, 2011))
来获取 grad_year 在 2000 至 2011 范围内的所有成员的 QuerySet
,无论 grad_year.is_certain
是否是真是假。
这可能吗?我知道我可以使用 Member.objects.filter(grad_year__contains="2011") 来获得第一个结果,但我希望能够使用 __year。
这是相关的类,删除了无关的代码:
class YearWithSureness(object):
def __init__(self, year='', is_certain=False):
# ...
def __str__(self):
return "{year}/{is_certain}".format(year=self.year,
is_certain=self.is_certain)
class YearWithSurenessField(models.Field):
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
# ...
def to_python(self, value):
# ...
def get_prep_value(self, value):
# ...
def get_prep_lookup(self, lookup_type, value):
if lookup_type in ('month', 'day'):
raise TypeError('Lookup type {0} not supported.'.format(lookup_type))
else:
return super(YearWithSurenessField, self).get_prep_lookup(lookup_type, value)
def value_to_string(self, obj):
# ...
I have a custom model field YearWithSurenessField
which is represented in python by the custom datatype YearWithSureness
. The constructor for YearWithSureness
is YearWithSureness(year='', is_certain=False)
, where year
is either ''
or a four-digit year (as a string), and is_certain
is a bool representing whether or not I'm certain that the given year is correct. Model fields of this type are stored in my database in the form year/is_certain, e.g. "2008/True", "2011/False", "/False", etc.
As an example, in the Member
model, I have a field grad_year = YearWithSurenessField(...)
which stores a member's graduation year along with whether or not I know for certain that the year I stored is correct.
What I'd like to be able to do is use something like
Member.objects.filter(grad_year__year=2011)
to get a QuerySet
of all the Members whose grad_year is either "2011/True" or "2011/False". Similarly, I'd like to be able to use something like
Member.objects.filter(grad_year__range=(2000, 2011))
to get a QuerySet
of all the Members whose grad_year is in the range 2000 thru 2011 irrespective of whether grad_year.is_certain
is True or False.
Is this possible? I know that I could use Member.objects.filter(grad_year__contains="2011") to get the first result, but I'd like to be able to use __year.
Here're the relevant classes, trimmed of extraneous code:
class YearWithSureness(object):
def __init__(self, year='', is_certain=False):
# ...
def __str__(self):
return "{year}/{is_certain}".format(year=self.year,
is_certain=self.is_certain)
class YearWithSurenessField(models.Field):
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
# ...
def to_python(self, value):
# ...
def get_prep_value(self, value):
# ...
def get_prep_lookup(self, lookup_type, value):
if lookup_type in ('month', 'day'):
raise TypeError('Lookup type {0} not supported.'.format(lookup_type))
else:
return super(YearWithSurenessField, self).get_prep_lookup(lookup_type, value)
def value_to_string(self, obj):
# ...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是我发现有用的东西:
在 Django 中创建自定义字段查找
更灵活的方法是编写自定义查询集以及自定义管理器。使用 ozan 的代码:
这允许您链接自定义查询。所以这两个查询都是有效的:
Here's something that I found useful:
Creating custom Field Lookups in Django
A more flexible way to do this is to write a custom QuerySet as well as a custom manager. Working from ozan's code:
This allows you to chain your custom query. So both these queries would be valid:
我不明白为什么你需要这样一个自定义字段。据我所知,“year”和“is_certain”非常适合存储在两个独立的字段中。通过这样做,首先,按年份或年份范围进行搜索会更容易。其次,搜索的效率也会显着提高,尤其是当数据量很大时。最后但并非最不重要的一点是,您不再需要费心如何正确实现自定义字段。
因此,我建议您解释为什么需要将这两种自然不同类型的数据存储到数据库表中的单个列中的根本原因。也许我们可以指出一种更简单的方法来实现您的真正目标。
I can't understand why you need to have such a custom field. As far as I can see, 'year' and 'is_certain' are perfectly suitable to store in 2 separated fields. By doing so, first, searching by year or year range is easier. Second, searching will be also be significantly more efficient, especially when there are a large amount of data. Last but not least, you don't need to bother how to correctly implement a customized field anymore.
So I suggest you explain the fundamental reason why you need to store those two naturally disparate types of data into a single column in your database table. And maybe we can point out a simpler way to achieve your real goals.
您是否尝试过更改 get_prep_lookup 的行为,以在 Lookup_type == 'year' 时仅返回年份值?您可以返回 int(value.split('/')[0])
我不确定实现这样的自定义字段是最佳选择,是否有充分的理由避免将值拆分为两个单独的字段?
Have you tried to change the behavior of get_prep_lookup to return just the year value when lookup_type == 'year'? You could return int(value.split('/')[0])
I'm not sure implementing such a custom field is the best option, is there a really good reason to avoid splitting the values into two separated fields?