简体   繁体   English

如何为Django Model字段创建别名?

[英]How to create an alias for Django Model field?

My Django Model has a datetime field named 'updatedOn', I need to use a library function on this model to calculate some statistics, but the function assumes the datetime field name to be 'time', here is how the function uses the datetime: 我的Django模型有一个名为'updatedOn'的日期时间字段,我需要在此模型上使用库函数来计算一些统计信息,但该函数假定日期时间字段名称为'时间',这是函数使用日期时间的方式:

c = qset.filter(time__year=tt.year, time__month=tt.month, time__day=tt.day).count();

Without touching the library code, how can I create an alias 'time' to refer to 'updatedOn' field, so that I can use the function? 在不触及库代码的情况下,如何创建别名'time'来引用'updatedOn'字段,以便我可以使用该函数?

I haven't looked into this very deeply, but intuitively, some of the following ways might get you started. 我没有深入研究过这个问题,但直观地说,以下一些方法可能会让你开始。

Custom manager 定制经理

A custom manager with a modified get_queryset method to look for updatedOn when filtering for time . 具有修改的get_queryset方法的自定义管理器 ,用于在过滤time时查找updatedOn

Custom field type 自定义字段类型

It might be possible to create a custom field type which only acts as a reference to another field. 可以创建自定义字段类型 ,该类型仅用作对另一个字段的引用。

Hacking the model._meta.fields 攻击model._meta.fields

The model object's _meta.fields seems to contain the list of fields in that object. 模型对象的_meta.fields似乎包含该对象中的字段列表。 Maybe you could try adding some kind of dummy field called time , which refers to the updatedOn field. 也许你可以尝试添加一种称为time的虚拟字段,它指的是updatedOn字段。

This old Django Snippet , worked for me, until Django 1.11. 这个老Django Snippet ,为我工作,直到Django 1.11。 As @Jaberwocky commented virtual_only gets removed in Django 2.0 正如@Jaberwocky评论的那样,在Django 2.0中删除了virtual_only

However, the deprecation warning reads that this field is deprecated in favor of private_only , although this is not mentioned in the features removed of the above link. 但是, 弃用警告会读取此字段已弃用而不支持private_only ,尽管在上述链接中删除的功能中未提及此字段。

class AliasField(models.Field):
    # def contribute_to_class(self, cls, name, virtual_only=False):
    #       '''
    #           virtual_only is deprecated in favor of private_only
    #       '''
    #     super(AliasField, self).contribute_to_class(cls, name, virtual_only=True)
    #     setattr(cls, name, self)

    def contribute_to_class(self, cls, name, private_only=False):
        '''
            virtual_only is deprecated in favor of private_only
        '''
        super(AliasField, self).contribute_to_class(cls, name, private_only=True)
        setattr(cls, name, self)

    def __get__(self, instance, instance_type=None):
        return getattr(instance, self.db_column)


class Order(models.Model):
    """
    The main order model
    """
    number = AliasField(db_column='id')

Create a property for the field in your model: 为模型中的字段创建属性:

class MyModel(moels.Model):
    updated_on = models.DateTimeField()

    def _get_time(self):
        return self.updated_on
    time = property(_get_time)

following miikkas's suggestion re model.Manager, I came up with the following that works for the much simpler case of retrieving the id field by querying uuid. 遵循miikkas的建议re model.Manager,我提出了以下内容,它适用于通过查询uuid来检索id字段的更简单的情况。 the database was created with the ID being a varchar field used for a hexadecimal string, and I'm retrofitting a sequential integer ID field so I can use Django's auth module which requires it. 创建数据库的ID是一个用于十六进制字符串的varchar字段,我正在改进一个顺序整数ID字段,所以我可以使用需要它的Django的auth模块。 and I want to do this in steps, hence the hack. 我想分步进行,因此黑客攻击。

if DEVELOPMENT['merging_to_sequential_ids_incomplete']:
    class ModelManager(models.Manager):
        def get(self, *args, **kwargs):
            if 'uuid' in kwargs:
                kwargs['id'] = kwargs.pop('uuid')
            return super(ModelManager, self).get(*args, **kwargs)

class Model(models.Model):
    if DEVELOPMENT['merging_to_sequential_ids_incomplete']:
        print >>sys.stderr, 'WARNING: uuid now a synonym to id'
        id = models.CharField(max_length = 32,
            primary_key = True, default = uuid_string)
        objects = ModelManager()  # for Client.objects.get(uuid=...)
        uuid = property(lambda self: self.id)  # for client.uuid
    else:
        id = models.AutoField(primary_key = True)
        uuid = models.CharField(max_length = 32, ...

now I can: 现在我能:

cd myapp && ../djangopython manage.py shell
WARNING: uuid now a synonym to id
setting up special admin settings
Python 2.7.8 (default, Nov 18 2014, 16:29:10) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from myapp.models import *
>>> Client.objects.get(uuid=u'18b86bd7b58e4c0186f7654045ce81d9')
<Client: jc@example.net>
>>> _.uuid
u'18b86bd7b58e4c0186f7654045ce81d9'

filter could be done the same way. filter可以以相同的方式完成。

maybe this can help guide someone else looking for a way to use an "alias" or "synonym" for a Django model field. 也许这可以帮助指导其他人寻找一种方法来为Django模型字段使用“别名”或“同义词”。 I don't believe it will help the OP though. 我不相信它会对OP有所帮助。 the custom field type might be the better general approach. 自定义字段类型可能是更好的通用方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM