自定义 Django 模型字段的字段查找功能

发布于 2024-11-07 08:00:46 字数 1865 浏览 1 评论 0原文

我有一个自定义模型字段 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

束缚m 2024-11-14 08:00:46

这是我发现有用的东西:
在 Django 中创建自定义字段查找

更灵活的方法是编写自定义查询集以及自定义管理器。使用 ozan 的代码:

class PersonQuerySet(models.query.QuerySet):
    def in_age_range(self, min, max):
        return self.filter(age__gte=min, age__lt=max)

class PersonManager(models.Manager):
    def get_query_set(self):
         return PersonQuerySet(self.model)

    def __getattr__(self, name):
        return getattr(self.get_query_set(), name)

class Person(models.Model):
    age = #...
    objects = PersonManager()

这允许您链接自定义查询。所以这两个查询都是有效的:

Person.objects.in_age_range(20,30)
Person.objects.exclude(somefield = some_value).in_age_range(20, 30)

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:

class PersonQuerySet(models.query.QuerySet):
    def in_age_range(self, min, max):
        return self.filter(age__gte=min, age__lt=max)

class PersonManager(models.Manager):
    def get_query_set(self):
         return PersonQuerySet(self.model)

    def __getattr__(self, name):
        return getattr(self.get_query_set(), name)

class Person(models.Model):
    age = #...
    objects = PersonManager()

This allows you to chain your custom query. So both these queries would be valid:

Person.objects.in_age_range(20,30)
Person.objects.exclude(somefield = some_value).in_age_range(20, 30)
酸甜透明夹心 2024-11-14 08:00:46

我不明白为什么你需要这样一个自定义字段。据我所知,“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.

梦纸 2024-11-14 08:00:46

您是否尝试过更改 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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文