繁体   English   中英

具有对象字典和__dict__的Python / Django奇怪行为

[英]Python/Django Strange behavior with object dictionary and __dict__

我有一个Django项目的一部分,该项目涉及将单元应用程序提交到系统中,并且我注意到使用ORM查找应用程序,然后将该对象转换为调用__dict__的dict以预填充表单的奇怪行为。

我很好奇是否有人可以解释正在发生的事情或我做错了什么。 基本上,我的UnitApplication模型中有一个外键,因此应用程序被映射到Properties,这个数据库列名和Model中的属性名是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__)

到底是怎么回事? 我可以通过编辑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建议,尽管这样做并没有发生,这对我的需求而言并不理想。

只是想分享一种我想出的方法,可以使用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)

我的建议是实现一种以所需格式返回所需字段的方法。 __dict__并不意味着可以直接访问,并且可能会有一些内部操作导致您看到不一致的情况。

您的问题是您在UnitApplication字段命名为primary_id Django会自动将_id附加到任何外键字段中,因此您可以做到这一点使其变得多余。 如果查看实际数据库,则可以看到列名也将是property_id_id

要解决此问题,您可以将property_id字段重命名为property ,然后重新迁移。

__dict__更好的方法可能是使用values() ,它返回字典的查询集而不是模型对象,或者使用模型form

在模型中定义外键时,Django的作用是:将引用对象的主键保存在数据库表的<field_name>_id列中。

由于您将ForeignKey字段命名为property_id ,因此Django在数据库中创建了一个property_id_id列,用于保存外键。 (很明显,为什么约定要求在它们引用的Model之后命名外键字段,而在本例中为property而不添加_id 。)

您可以在任何UnitApplication对象上访问此属性。 以下内容将评估为true:

unitapp.property_id_id == unitapp.property_id.id

在这两种情况下,您都将访问相关对象的主键,一次是从主模型中,一次是从相关模型中。

当您在模型对象上调用__dict__时,外键仅表示为ID,其键为列名。 您没有获得实际相关对象的句柄。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM