Использование save() в модели Django приводит к TypeError

***** Работа с Django 1.11.x и Python 3.6*****

Я пытаюсь узнать, как использовать метод save() в модели Django (models.py). Здесь есть два поля, которые я хочу сделать пользовательскими, "вычисляемые" поля (unique_id и age).

Сначала я инициирую переменные поля, затем определяю методы / свойства на основе существующих полей, затем пытаюсь сохранить результаты метода в созданные мной поля.

from django.db import models
from dateutil.relativedelta import relativedelta
from datetime import datetime

class Person(models.Model):
    unique_id = models.CharField(max_length=6, primary_key=True)
    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, **kwarg):
        self.unique_id = self.get_unique_id()
        self.age = self.get_age()
        super(Person, self).save(*args, **kwarg)

    def __str__(self):
        return self.unique_id

Сначала я создаю 5 полей. 2 из них являются заполнителями: unique_id и age. Затем я определяю два метода @property, каждый из которых возвращает результат другого типа. Функция "get_unique_id" работает, но я не могу получить результат, сохраненный в базе данных. Функция get_age может работать или не работать. Я еще не смог произвести это.

Мой основной вопрос - как правильно использовать функцию save() для переопределения начальных значений полей (unique_id и age) с помощью моих методов "вычисляемого поля" (get_unique_id и get_age).

Моя основная проблема заключается в том, что когда я добавляю Person (используя Person ModelForm в /Admin), он создает объект TypeError: 'str', который нельзя вызвать в строке "self.unique_id = self.get_unique_id ()". В настоящее время я использую интерфейс администратора для тестирования.

В конце концов мне нужно научиться НЕ отображать эти 2 поля в формах, так как они будут рассчитываться на основе других полей. Думаю, я нашел документацию по Meta, которая может помочь. Кроме того, я хочу, чтобы поле unique_id было первичным ключом, поэтому я добавил эту опцию в начальное поле.

У меня есть вторичный вопрос (мои извинения за то, что я новичок в Django) о *args и **kwargs. Можно ли оставить их там? Я действительно не уверен, какие аргументы мне нужно использовать, если таковые имеются, и нужно ли включать в код *args и **kwargs.

ПРИМЕЧАНИЕ: всем, кто помог мне вчера с этим приложением, я очень ценю вашу помощь. Я считаю, что это отличается от моего предыдущего вопроса, хотя я использую большую часть того же кода.

1 ответ

Решение

Свойства не могут быть вызваны. Когда вы получаете доступ self.get_unique_id, Python делает вызов базового метода, оформленного @property за кулисами, который в этом случае возвращает строку. Вам не нужно звонить снова, бросьте паренсы:

def save(self, *args, **kwarg):
    self.unique_id = self.get_unique_id
    self.age = self.get_age
    super(Person, self).save(*args, **kwarg)

OTOH, исходя из комментария @DanielRoseman, вам не нужно хранить возраст в базе данных. Просто посчитайте, когда это необходимо. Вы могли бы переименовать get_age как age и бросить age поле, так age становится собственностью.

Другие вопросы по тегам