Python / Django Странное поведение с объектным словарем и __dict__ - PullRequest
0 голосов
/ 03 апреля 2019

У меня есть часть проекта Django, которая включает в себя отправку квартирных приложений в систему, и я замечаю странное поведение при поиске приложения с использованием ORM, а затем превращаю объект в dict, вызывающий __dict__ для предварительного заполненияформа.

Мне любопытно, кто-нибудь может объяснить, что происходит, или что я делаю неправильно.По сути, у меня есть внешний ключ в моей модели UnitApplication, поэтому приложения сопоставляются со свойствами, имя этого столбца базы данных и имя атрибута в моей модели равно property_id, однако, когда я превращаю объект в словарь, он добавляет дополнительный _id к названию поля.

Вот мой код:

application_id = request.GET.get('application_id')
application = UnitApplication.objects.using(db_alias).get(id=application_id)

# this is in a view so property_id == Property Object (1)
print(application.property_id)

# this will print my actual property_id, which is 1
print(application.property_id.id)

# this is the odd behavior, here is the dict that prints, and hinders form filling
# {..., 'property_id_id': 1, ...}

print(application.__dict__)

Что происходит?Я могу исправить это, отредактировав диктат, но я чувствую, что это глючит.

Вот соответствующие части моей модели, если вам интересно мое именование:

class Property(models.Model):
    # I know this isn't needed but it makes me feel better seeing it here
    id = models.AutoField(primary_key=True)

    rental_add_ons = models.ManyToManyField('RentalAddOns', related_name='rental_add_ons')

    date_added = models.DateTimeField(auto_now_add=True, editable=False)

    ...

class UnitApplication(models.Model):

    # property id, set to null if property removed from db
    property_id = models.ForeignKey('Property', 
                                    null=True, 
                                    on_delete=models.SET_NULL,
                                    db_column='property_id')

Примечание: Я использую обычный Form для этого, потому что это дало мне немного больше свободы, я не ищу предложений по изменению этого варианта использования Model Form, я сделал это, ихотя этой проблемы там не бывает, она не была идеальной для моих нужд.

Ответы [ 4 ]

1 голос
/ 03 апреля 2019

Просто хотел поделиться способом, который я выяснил, чтобы превратить объект в словарь, используя встроенные функции Django. Из комментариев и ответов здесь показалось, что я не должен использовать __dict__.

from django.forms import model_to_dict

application = UnitApplication.objects.get(id=request.GET.get('application_id'))

accurate_dictionary = model_to_dict(application)
print(accurate_dictionary)

Теперь это работает:

form = UnitApplicationForm(initial=accurate_dictionary)
0 голосов
/ 03 апреля 2019

Ваша проблема в том, что вы назвали свое поле primary_id в UnitApplication.Django автоматически добавляет _id к любому полю, являющемуся иностранным ключом, поэтому его выполнение делает его избыточным.Если вы просматриваете свою фактическую базу данных, вы можете видеть, что имя столбца также будет property_id_id.

. Чтобы исправить это, вы можете переименовать поле property_id в property, а затем выполнить повторную миграцию.

0 голосов
/ 03 апреля 2019

Лучшим подходом, чем __dict__, может быть использование values(), который возвращает набор словарей вместо объектов модели, или использование форм моделей .

Что делает Django, когда вы определяете внешний ключ в модели, так это: он сохраняет первичный ключ упомянутого объекта в таблице базы данных в столбце <field_name>_id.

Поскольку вы назвали свое поле ForeignKey property_id, Django создал в базе данных столбец property_id_id, в который нужно сохранить внешний ключ. (Очевидно, что соглашение требует именовать поля внешнего ключа после модели, на которую они ссылаются, без добавления _id, в данном случае property.)

Вы можете получить доступ к этому атрибуту на любом объекте UnitApplication. Следующее оценило бы как истинное:

unitapp.property_id_id == unitapp.property_id.id

В обоих случаях вы обращаетесь к первичному ключу связанного объекта, один раз из основной модели, один раз из связанной модели.

Когда вы вызываете __dict__ для объекта модели, внешние ключи представляются просто идентификаторами, а их ключ - именем столбца. Вы не получите указатель на фактический связанный объект.

0 голосов
/ 03 апреля 2019

Я бы предложил реализовать метод, который возвращает нужные поля в нужном вам формате. __dict__ не предназначен для прямого доступа, и могут быть некоторые внутренние операции, которые вызывают несоответствие, которое вы видите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...