2017-06-28 23 views
3

使用Django〜= 1.11和Python 3.6Django的模型法或計算的場數據庫

我需要存儲「計算」變量中的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) 

我創建使用這些字段一個唯一的ID。具體地講,我conjoining每個場的一部分結合到一個字符串變量(細節如下)。我能得到這個作爲一個物業工作,但我不知道如何計算的字段存儲在數據庫中。

"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) 

我想和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) 

所以我想給的UniqueID和年齡變量存儲在數據庫中,如在Person模型領域。這樣做的最佳做法是什麼?我是否需要首先初始化字段,然後對這些進行某種更新查詢?

注:這是我的理解是用「財產」目前的代碼工作在視圖渲染,但它並不存儲在數據庫中。

在此先感謝!請幫我改進我已有的東西。

更新: 這是我工作的代碼。問題是,我需要刪除括號在保存()段,後self.unique_id = self.get_unique_id。有人建議從數據庫中刪除年齡,並將其作爲財產。

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 
+0

你已經完成了大部分工作。你只需要爲你的模型創建一個自定義的保存功能,那樣做。 –

+0

請提供具體代碼的答案。到目前爲止我還沒有找到功能性答案。 –

回答

4

您必須重寫模型Person中的save方法並在模型中創建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) 
+0

另外我建議使用''relativedelta''來計算日期時間差異。 – josemlp

+0

我正在尋找如何使用relativedelta,但不知道如何做到這一點。如果你可以編輯你的代碼,我會非常感激! –

+0

@RonRaney完成! – josemlp

1

模型對這種事情clean方法:

這個方法應該用於提供自定義模型驗證,並且如果需要的話你的模型修改屬性。例如,你可以用它來爲現場自動提供一個值,或者要做到這一點,需要獲得超過單場

因此失去了財產,並添加一個名爲「UNIQUE_ID」字段應該是驗證一個CharField。重命名get_idclean,代之以return語句:

self.unique_id = a + b + c 

如果你確定這總是生成一個唯一的字符串,考慮使這一領域的主鍵。然而,如果這種模式已經被遷移,你不能將其命名爲id,因爲Django的已經創建了一個場id作爲AutoField你,所以如果你的名字「ID」(設置將採取兩個遷移,你可以壓扁)。

+0

謝謝。我想我現在遇到的問題是形式。如果我進入/ Admin創建一個對象,它需要我爲UniqueID和Age添加一個值。我希望這些在輸入表單後進行計算。我試圖在字段類型選項中放入「required = False」,但它給了我錯誤。 –

+0

您可以從ModelAdmin中[排除字段](https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#django.contrib.admin.ModelAdmin.exclude),因爲它使用[ModelForm] (https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/#selecting-the-fields-to-use)。另外,模型字段中的「blank = True」使其不是必需的,但爲了正常工作,它不能成爲主鍵。 – Melvyn

+0

任何想法如何處理?當我點擊保存時,該模型的ModelForm需要這些值。我不確定如何將它包含在視圖中。我應該爲此打開另一個問答嗎? 異常值:save()缺少2個必需的位置參數:'get_unique_id'和'get_age' –