简体   繁体   English

Django 模型方法或计算作为数据库中的字段

[英]Django Model Method or Calculation as Field in Database

Using Django ~=1.11 and Python 3.6使用 Django ~=1.11 和 Python 3.6

I need to store 'calculated' variables as fields in the Django model database.我需要将“计算”变量存储为 Django 模型数据库中的字段。

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.我正在使用这些字段创建唯一 ID。 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.我想对 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.所以我想将 UniqueID 和 Age 变量存储在数据库中,作为 Person 模型中的字段。 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 .问题是我需要在self.unique_id=self.get_unique_id之后删除save() 部分中的括号。 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

You have to override the save method of yout Model Person and create unique_id and age field in the Model.您必须覆盖 Model Personsave方法并在 Model 中创建unique_idage字段。

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)

UPDATE: Previously the self.get_unique_id and self.get_age were being called with '()' which is not required for class properties.更新:以前self.get_unique_idself.get_age是用 '()' 调用的,这不是类属性所必需的。

A model has a clean method for this kind of thing:模型对这种事情有一个clean方法:

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.所以松开属性并添加一个名为“unique_id”的字段,它应该是一个 CharField。 Rename get_id to clean and replace the return statement with:重命名get_idclean并将返回语句替换为:

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).但是,如果此模型已经迁移,则不能将其命名为id ,因为 Django 已经为您创建了一个字段id作为AutoField ,因此如果您设置了名称 'id'(您可以稍后南瓜)。

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

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