Объект 'NoneType' не имеет атрибута 'customer_id'
У меня есть две модели в приложении под названием customer. Модели Customer и Account. Логика заключается в том, что у одного клиента может быть много счетов. Поэтому автоматически сгенерированный по умолчанию столбец 'id' в Customer является внешним ключом в Account. Account также имеет автоматически генерируемый по умолчанию столбец 'id'. Я создал функцию для поля account_id в Account, которое будет генерироваться по простому алгоритму. customer_id и id из Account будут конкатенированы как 'customer_id'_'id', (например, 1_1). Функция сначала проверит текущий customer_id созданного экземпляра Account, а затем проверит, какой последний id для этого customer_id. Для вновь добавленного счета будет захвачена часть id из account_id (т.е. часть после подчеркивания) и увеличена на 1. Затем произойдет конкатенация для тех же customer_id и id. Ниже приведен код:
models.py
from asyncio.windows_events import NULL
from django.db import models
from django.db.models.signals import pre_save
from django.contrib.auth.models import AbstractBaseUser
from .utils import set_account_id
class Customer(AbstractBaseUser):
name = models.CharField(max_length=50)
phone = models.BigIntegerField(null=True)
email = models.EmailField(max_length=100, null=True)
org_name = models.CharField(max_length=100, null = True)
org_logo = models.ImageField(upload_to='logos', blank=True)
subscription_start_date = models.DateField()
subscription_end_date = models.DateField()
password = models.CharField(max_length=50, blank=True, null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'email']
def __str__(self):
return self.name
class Account(AbstractBaseUser):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
account_id = models.CharField(max_length=100, default=None, blank=True, null=True)
name = models.CharField(max_length=50)
phone = models.BigIntegerField(null=True)
email = models.EmailField(max_length=100, null=True)
password = models.CharField(max_length=50, blank=True, null=True)
account_type = models.CharField(max_length=50, choices=[
("survey", "SURVEY"),
("sme", "SME"),
("residents", "RESIDENTS")
])
account_subscription_date = models.DateField(null=True)
account_expiry_date = models.DateField(null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'email']
def __str__(self):
return self.name
def pre_save_set_account_id(sender, instance, *args, **kwargs):
if not instance.account_id:
instance.account_id = set_account_id(instance) #Error here
print(instance.account_id)
pre_save.connect(pre_save_set_account_id, sender=Account)
utils.py
def set_account_id(instance):
Klass = instance.__class__
fk = 'customer_id'
obj = Klass.objects.first()
field_object = Klass._meta.get_field(fk)
fk_value = field_object.value_from_object(obj) #Error here
last_account = Klass.objects.filter(customer_id=fk_value).all().order_by('id').last()
accounts_pk = last_account.id
new_account_int = accounts_pk + 1
new_account_id = fk_value + '_' + new_account_int
return new_account_id
Теперь, когда я ввел одну запись в >customer и пытаюсь ввести запись в account через панель администратора. Когда я заполняю форму для account в панели администратора, я оставляю account_id пустым. После нажатия на Save, я получаю следующую ошибку-:
AttributeError at /admin/customer/account/add/ Объект 'NoneType' не имеет атрибута 'customer_id'
Я закомментировал "Error here" в конкретных строках, в которых ошибка была указана отладчиком Django. Я новичок в Django и много чего перепробовал, но не смог устранить ошибку. Пожалуйста, помогите.
Эй, я не знаю, зачем вам вообще нужен этот account_id как поле db? Если он нужен вам для фильтрации, я предлагаю использовать сигнал post_save, например:
def post_save_set_account_id(sender, instance, *args, **kwargs):
if instance.account_id is None:
instance.account_id = f'{instance.customer.id}_{instance.id}'
instance.save()
Но если вам не нужно строить sql запрос на основе поля account_id, я предлагаю использовать @property в модели Account:
@property
def account_id(self):
return f'{self.id}_{self.account.id}'
тогда вы можете использовать его как поле модели, например:
account = Account.objects.get(pk=1)
account.account_id
печатает, например:
1_1