web-dev-qa-db-ja.com

Djangoデータベースのフィールドとしてのモデルメソッドまたは計算

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
8
Ron Raney

モデルsavePersonメソッドをオーバーライドし、モデルに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)
15
josemlp

モデルには、この種のことのための clean メソッドがあります。

このメソッドは、カスタムモデルの検証を提供し、必要に応じてモデルの属性を変更するために使用する必要があります。たとえば、フィールドの値を自動的に提供したり、複数のフィールドへのアクセスを必要とする検証を行ったりするために使用できます。

したがって、プロパティを緩め、CharFieldである必要がある 'unique_id'という名前のフィールドを追加します。名前を変更するget_idからcleanに移動し、returnステートメントを次のように置き換えます。

self.unique_id = a + b + c

これにより常に一意の文字列が生成されることが確実な場合は、このフィールドを主キーにすることを検討してください。ただし、このモデルがすでに移行されている場合は、idという名前を付けることはできません。DjangoはすでにフィールドidAutoFieldとして作成しているためです。そのため、「id」という名前を設定している場合は、2回の移行が必要になります(後で押しつぶすことができます)。

3
Melvyn