How to create an alias for Django Model field?
Solution 1
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
.
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
The model object's _meta.fields
seems to contain the list of fields in that object. Maybe you could try adding some kind of dummy field called time
, which refers to the updatedOn
field.
Solution 2
This old Django Snippet, worked for me, until Django 1.11. As @Jaberwocky commented virtual_only
gets removed in Django 2.0
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.
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')
Solution 3
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)
Solution 4
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. 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. 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: [email protected]>
>>> _.uuid
u'18b86bd7b58e4c0186f7654045ce81d9'
filter
could be done the same way.
maybe this can help guide someone else looking for a way to use an "alias" or "synonym" for a Django model field. I don't believe it will help the OP though. the custom field type might be the better general approach.
Related videos on Youtube
NeoWang
Coder and Enterpreneur. Have worked on Web backend (Python/Django/Tornado), FrontEnd(jQuery/Backbone/Bootstrap/Angular), iOS/Android, embedded developement, also interested in Machine Learning/NLP stuff. Have cofounded a startup on a site-builder SaaS product, failed due to lack of marketing experience. Now working at an Internet start-up. SOreadytohelp
Updated on September 14, 2022Comments
-
NeoWang over 1 year
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:
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?
-
NeoWang over 10 yearsThe property can be used to query the value, but cannot be used in qset.filter(time__year=tt.year...).
-
hellsgate over 10 yearsAh, that's annoying :-(
-
addohm over 6 yearsbrace yourself. Django 2.0 gets rid of virtual_only.
-
raratiru over 6 years@Jaberwocky Wow, thank you, that's the issue with the old snippets!
-
addohm over 6 yearsno problem. For the record, in 2.0 you can mostly copy\paste the doc examples and they'll work (unlike 1.11). I did that and made some minor tweaks to add fields to the user model, as well as assign the id a UUID4. I used the source file templates and trimmed\styled them. It was pretty quick and painless.
-
raratiru over 6 years@Jaberwocky I found out the deprecation message which reads that
virtual_only
is removed in favor ofprivate_only
. This is not clear for some reason in the "removed features" section. I have updated the answer accordingly. -
Vladimir Osintsev about 2 yearsThis is also can be written inline as
time = property(lambda self: self.updated_on)