问题
Using Django ~=1.11 and Python 3.6
I need to store 'calculated' variables as fields in the Django model database.
Here's a model:
from django.db import models
from datetime import date
class Person(model.Model)
"Last Name"
last_name = models.CharField(max_length=25)
"Birthday"
birth_date = models.DateField()
"City of birth"
city_of_birth = models.CharField(max_length=25)
I am creating a Unique ID using these fields. Specifically, I'm conjoining parts of each field into one string variable (details below). I was able to get this to work as a Property but I don't know how to store a calculated field in the database.
"Unique ID"
def get_id(self):
a = self.last_name[:2].upper() #First 2 letters of last name
b = self.birth_date.strftime('%d') #Day of the month as string
c = self.city_of_birth[:2].upper() #First 2 letters of city
return a + b + c
unique_id = property(get_id)
I want to do a similar thing with Age. Here's what I have as a calculation:
"Age calculated from Birth Date"
def get_age(self):
return int((datetime.date.now() - self.birth_date.days) / 365.25)
age = property(get_age)
So I'd like to store the UniqueID and Age variables in the database, as fields in the Person model. What is the best practice when doing these? Do I need to initialize the fields first, then do some sort of update query to these?
Note: It is my understanding that the current code using 'property' works for rendering in the view, but it is not stored in the database.
Thanks in advance! Please help me improve what I already have.
UPDATE: Here is code that worked for me. The problem was that I needed to drop the parentheses in the save() section, after self.unique_id=self.get_unique_id . It has been suggested to drop age from the database, and leave it as a property.
class Person(models.Model):
unique_id = models.CharField(max_length=6, blank=True)
last_name = models.CharField(max_length=25)
birth_date = models.DateField()
city_of_birth = models.CharField(max_length=25)
@property
def get_unique_id(self):
a = self.last_name[:2].upper() #First 2 letters of last name
b = self.birth_date.strftime('%d') #Day of the month as string
c = self.city_of_birth[:2].upper() #First 2 letters of city
return a + b + c
@property
def age(self):
return relativedelta(self.birth_date.days, datetime.date.now()).years
def save(self, *args, **kwarg):
self.unique_id = self.get_unique_id
super(Person, self).save(*args, **kwarg)
def __str__(self):
return self.unique_id
回答1:
You have to override the save
method of yout Model Person
and create unique_id
and age
field in the Model.
from dateutil.relativedelta import relativedelta
from datetime import datetime
class Person(model.Model)
unique_id = models.CharField(max_length=25)
age = models.IntegerField()
last_name = models.CharField(max_length=25)
birth_date = models.DateField()
city_of_birth = models.CharField(max_length=25)
@property
def get_unique_id(self):
a = self.last_name[:2].upper() #First 2 letters of last name
b = self.birth_date.strftime('%d') #Day of the month as string
c = self.city_of_birth[:2].upper() #First 2 letters of city
return a + b + c
@property
def get_age(self):
return relativedelta(self.birth_date.days, datetime.date.now()).years
def save(self, *args, **kwargs):
self.unique_id = self.get_unique_id()
self.age = self.get_age()
super(Person, self).save(*args, **kwargs)
回答2:
A model has a clean method for this kind of thing:
This method should be used to provide custom model validation, and to modify attributes on your model if desired. For instance, you could use it to automatically provide a value for a field, or to do validation that requires access to more than a single field
So loose the property and add a field named 'unique_id' which should be a CharField. Rename get_id
to clean
and replace the return statement with:
self.unique_id = a + b + c
If you're certain this always generates a unique string, consider making this field the primary key. However, if this model is already migrated, you cannot name it id
, since Django has already created a field id
as an AutoField
for you, so it will take two migrations if you're set on the name 'id' (which you can squash later).
来源:https://stackoverflow.com/questions/44805303/django-model-method-or-calculation-as-field-in-database