Django Model Method or Calculation as Field in Database

|▌冷眼眸甩不掉的悲伤 提交于 2020-05-10 05:22:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!