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)
これらのフィールドを使用して一意のIDを作成しています。具体的には、各フィールドの一部を1つの文字列変数に結合しています(詳細は以下を参照)。これをプロパティとして機能させることはできましたが、計算フィールドをデータベースに保存する方法がわかりません。
"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 calculated from Birth Date"
def get_age(self):
return int((datetime.date.now() - self.birth_date.days) / 365.25)
age = property(get_age)
そこで、Personモデルのフィールドとして、UniqueID変数とAge変数をデータベースに保存したいと思います。これらを行うときのベストプラクティスは何ですか?最初にフィールドを初期化してから、これらに対して何らかの更新クエリを実行する必要がありますか?
注:「property」を使用している現在のコードはビューでのレンダリングには機能しますが、データベースには保存されないことを理解しています。
前もって感謝します!私がすでに持っているものを改善するのを手伝ってください。
PDATE:これが私のために働いたコードです。問題は、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
モデルsave
のPerson
メソッドをオーバーライドし、モデルにunique_id
およびage
フィールドを作成する必要があります。
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)
モデルには、この種のことのための clean
メソッドがあります。
このメソッドは、カスタムモデルの検証を提供し、必要に応じてモデルの属性を変更するために使用する必要があります。たとえば、フィールドの値を自動的に提供したり、複数のフィールドへのアクセスを必要とする検証を行ったりするために使用できます。
したがって、プロパティを緩め、CharFieldである必要がある 'unique_id'という名前のフィールドを追加します。名前を変更するget_id
からclean
に移動し、returnステートメントを次のように置き換えます。
self.unique_id = a + b + c
これにより常に一意の文字列が生成されることが確実な場合は、このフィールドを主キーにすることを検討してください。ただし、このモデルがすでに移行されている場合は、id
という名前を付けることはできません。Djangoはすでにフィールドid
をAutoField
として作成しているためです。そのため、「id」という名前を設定している場合は、2回の移行が必要になります(後で押しつぶすことができます)。