Для доступа к значению поля пользовательской модели Django (неосновное BigAutoField) после сохранения

#django #django-models #autofield

#django #django-модели #автоматическое поле

Вопрос:

У меня есть настраиваемое поле Django «BigAutoField» в одной из моих моделей. Это не первичный ключ. Я использую uuid в качестве своего первичного ключа. При вставке все работает нормально. Я получаю новую запись в базе данных mysql с автоматически увеличенным значением этого поля. Но проблема в том, что после сохранения экземпляр модели не может получить значение этого поля. (точечная нотация не работает). Я должен снова получить экземпляр объекта, чтобы получить доступ к его значению. Кто-нибудь может мне помочь, как получить доступ к значению без перезагрузки?


 class BigAutoField(models.PositiveIntegerField):
__metaclass__ = models.SubfieldBase

def __init__(self, *args, **kwargs):
    self.sequence_name = kwargs.pop('sequence_name', None)
    kwargs['blank'] = True
    kwargs['editable'] = False
    kwargs['null'] = False
    kwargs['unique'] = True
    super(BigAutoField, self).__init__(*args, **kwargs)

def db_type(self, connection):
    engine = settings.DATABASE_ENGINE
    if engine[-5:] == 'mysql':
        return 'bigint AUTO_INCREMENT'
    elif engine == 'oracle':
        return 'NUMBER(19)'
    elif engine[:8] == 'postgres':
        return 'bigserial'
    else:
        raise NotImplemented()

def get_internal_type(self):
    return 'BigAutoField'

def to_python(self, value):
    if value is None:
        return value
    try:
        return long(value)
    except (TypeError, ValueError):
        raise exceptions.ValidationError(
                _("This value must be a long integer."))

def get_db_prep_value(self, value, connection=None, prepared=False):
    if value is None:
        return value
    return long(value)
  

Это мой пользовательский класс bigautofield. В первый раз, когда я выполняю сохранение для модели, используя это поле, оно работает fine.eg .

     x= XYZ.objects.create(a='a',b='b')
    x.save()
  

Но теперь я не могу получить доступ к x.c, где c — это BigAutoField в XYZ. Хотя в базе данных mysql для того же видно автоматически добавленное значение.

Комментарии:

1. Добавьте некоторый код, чтобы мы могли видеть, что вы делаете

2. Что означает: «не удалось получить значение этого поля. (точечная нотация не работает) «. ? Возникает ошибка? Поле не содержит ничего?

3. @danihp: да, значение поля остается пустым. Но я могу получить к нему доступ, если я снова перезагружу объект.

4. Значение ‘IDENTITY’ или ‘auto_increment’ устанавливается в базе данных, если по этой причине вы не можете прочитать значение в объекте python. После сохранения вы / django должны прочитать из базы данных присвоенный номер: как вы знаете, это механизм базы данных, который присваивает значение. Возможно, BigAutoField должно передаваться из AutoField вместо PositiveIntegerField.

Ответ №1:

У меня было особое требование иметь uuid в качестве первичного ключа и 1 поле в качестве автозаполнения в таблице. поскольку django не допускает автозаполнения, не являясь первичным ключом, мне пришлось наследовать его из поля положительных целых чисел.Чтобы решить эту проблему, мне пришлось реализовать функцию предварительного сохранения. Это приведет к извлечению следующего ключа автоматического увеличения из базы данных mysql и установит значение атрибутов перед вставкой. Таким образом, мои значения теперь сохраняются правильно, и я также могу получить к ним доступ.

  def pre_save(self, model_instance, add):
    if self.sequence_name is None:
        self.sequence_name = '%s' % (model_instance._meta.db_table)
    old_val = getattr(model_instance, self.attname)
    if add and old_val is None:
        cursor = connection.cursor()
        cursor.execute("SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'knowlus' AND TABLE_NAME = %s", [unicode(self.sequence_name)])
        val = long(cursor.fetchone()[0])
        discard = cursor.fetchall()
        setattr(model_instance, self.attname, val)
        return val
    else:
        return long(old_val)