我有一个模特:
class Person (models.Model):
name = models.CharField ()
birthday = models.DateField ()
age = models.IntegerField ()
我想让age
字段表现得像一个属性:
def get_age (self):
return (datetime.datetime.now() - self.birthday).days // 365
age = property (get_age)
但与此同时我需要age
成为真正的字段,因此我可以在Person._meta.fields
中找到它,并为其指定属性:age.help_text = "Age of the person"
等。
显然我不能只重写Person.save()
方法来计算和存储age
数据库,因为以后它不可避免地会出错(事实上,它根本不应该存储在数据库中)
实际上,我现在不需要设置setter,但一个不错的解决方案必须具有设置功能。</ p>
是否有可能在Django,或者可能有更多的pythonic和djangoic方法解决我的问题?
答案 0 :(得分:3)
如果您需要根据年龄进行查询,请考虑年龄,然后搜索符合要求的生日。
from datetime import datetime
# get people over 50
age = 50 # in years
age_ago = datetime.now() - age # use timedelta i don't know the syntax off the top of my head
Person.objects.filter(birthday__lte=age_ago) # people whose birthday is before fifty years ago
你自己说过“[年龄]根本不应该存储在数据库中”
你是对的。没有理由拥有年龄领域...只是财产会没事。答案 1 :(得分:1)
另一种可能更简单的方法是在管理模型中使用自定义表单。 像这样:
class Person (models.Model):
birthday = models.DateField()
class PersonForm(forms.ModelForm):
age = forms.IntegerField() # This will not be in the database
class Meta:
model = Person
def __init__(self, *args, **kwargs):
# verify instance was passed
instance = kwargs.get('instance')
if instance:
self.base_fields['age'].initial = (datetime.datetime.now() - self.birthday).days
super(PersonForm, self).__init__(*args, **kwargs)
class FooAdmin(admin.ModelAdmin):
form = PersonForm
# Save the age in the birthday field
def save_model(self, request, obj, form, change):
obj.birthday = datetime.datetime.now() + form.cleaned_data['age']
obj.save()
答案 2 :(得分:0)
我认为解决方案是为生日字段创建自定义窗口小部件。 您只想更改生日的显示方式和编辑方式。 这正是小部件的目的。
抱歉,我没有相应的代码,但这是一个很好的起点:
答案 3 :(得分:0)
您可以使用django-computed-property来实现。
您首先必须使用以下命令来安装 django-computing-property :
pip install django-computed-property
然后,您在 settings.py 中将computed_property
添加到INSTALLED_APPS
的列表中:
INSTALLED_APPS = [
...
'computed_property'
]
现在,您可以像这样导入和使用模型中包含的字段类:
from django.db import models
from computed_property import ComputedTextField
import random
class Person(models.Model):
age = ComputedTextField(compute_from='calculation')
@property
def calculation(self):
return str(random.randint(1,101))
Person模型上的age字段在每次调用时都会返回一个随机数,以证明它是在运行时计算得出的。
您可以照常从“年龄”字段中读取值,但可能没有设置 字段的值。何时访问字段以及何时建立模型 实例已保存,它将使用来计算该字段的值 提供的可调用(函数/ lambda),属性
age
或属性age