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

Ron*_*ney 7 python django methods django-models calculated-field

使用Django~ = 1.11和Python 3.6

我需要将"计算"变量存储为Django模型数据库中的字段.

这是一个模型:

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)
Run Code Online (Sandbox Code Playgroud)

我正在使用这些字段创建唯一ID.具体来说,我将每个字段的部分组合成一个字符串变量(详情如下).我能够将其作为属性工作,但我不知道如何在数据库中存储计算字段.

"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)
Run Code Online (Sandbox Code Playgroud)

我想和Age做类似的事情.这是我的计算结果:

"Age calculated from Birth Date"
def get_age(self):
    return int((datetime.date.now() - self.birth_date.days) / 365.25)
age = property(get_age)
Run Code Online (Sandbox Code Playgroud)

所以我想将UniqueID和Age变量存储在数据库中,作为Person模型中的字段.这样做的最佳做法是什么?我是否需要首先初始化字段,然后对这些字段进行某种更新查询?

注意:据我所知,使用'property'的当前代码适用于在视图中呈现,但它不存储在数据库中.

提前致谢!请帮助我改进我已有的东西.

更新: 这是适合我的代码.问题是我需要在self.unique_id = self.get_unique_id之后删除 save()部分中的括号.有人建议从数据库中删除年龄,并将其保留为属性.

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
Run Code Online (Sandbox Code Playgroud)

小智 14

您必须覆盖save模型的方法,并在模型中Person创建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)
Run Code Online (Sandbox Code Playgroud)

  • 往上看。需要在“ self.get_unique_id()”之后加上括号。谢谢! (3认同)

小智 5

模型有一个clean处理这种事情的方法:

此方法应用于提供自定义模型验证,并根据需要修改模型的属性。例如,您可以使用它自动为字段提供值,或者进行需要访问多个字段的验证

因此,松开该属性并添加一个名为“unique_id”的字段,该字段应该是 CharField。重命名get_idclean并将 return 语句替换为:

self.unique_id = a + b + c
Run Code Online (Sandbox Code Playgroud)

如果您确定这始终会生成唯一的字符串,请考虑将此字段设为主键。然而,如果这个模型已经迁移,你就不能命名它id,因为 Django 已经为你创建了一个字段idAutoField所以如果你设置名称“id”(你可以稍后压缩),那么将需要两次迁移。