Использование 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
становится собственностью.