如何在Django中为模型添加临时字段?

时间:2009-12-12 06:37:31

标签: django json django-models model

我正在开发一个Web应用程序,用户可以在其中创建多个相关元素,然后将这些元素保存到数据库中。 webapp不知道主键在数据库中的含义,因此它为每个元素分配一个UUID。这些UUID与数据库中的每个元素一起保存。当webapp将数据发送到Web服务器以放入数据库时​​,它使用JSON对所有内容进行编码。然后,网络服务器使用serializers.deserialize('json', DATA)对JSON进行反序列化。但是,某些模型具有外键,这些外键在JSON有效内容中作为对相关元素的UUID而不是数据库ID的引用发送。例如,我们可能有一个简单的链接对象:

class Link(models.Model):
    uuid = models.CharField(max_length=32)
    source = models.ForeignKey(Node, related_name='source')
    target = models.ForeignKey(Node, related_name='target')

如果源的id值为2且目标的id值为12,则会将其序列化为JSON,如下所示:

{"uuid": "[some long uuid]",
 "source": 2,
 "target": 12}

但是,因为在这种情况下我们不知道源和目标的数据库ID,可能是因为它们还没有设置,我能做的最好就是传递UUID这样:

{"uuid": "[some long uuid]", 
 "sourceuuid": "[uuid of source]", 
 "targetuuid": "[uuid of target]"}

不幸的是,当我在数据上调用FieldDoesNotExist: Link has no field named u'sourceuuid'时,这会引发serializers.deserialize的例外。

我想找到一种方法,我可以传递UUID,然后在保存适当的部分或在必要时查找它们之后让数据库填入id。我不想在数据库中保存sourceuuidtargetuuid,因为保存整数的空间要少得多,而且指标也应该更快。

所以,我正在寻找的是一个临时领域。我可以实例化和引用的,但它永远不会保存回数据库。关于如何制作这样的东西的任何想法?

更新更清晰

感谢您的帮助到目前为止,我知道它们是Python对象,我可以为对象分配任意字段。但是,问题是serializers.deserialize('json', INDATA)会抛出错误。

作为参考,这里是反序列化程序喜欢的一大块JSON,它有外键及其ID:

ser='''[{"pk": 1, "model": "myapp.link", 
         "fields": {"uuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                    "source": 2,
                    "target": 12}}]'''
serializer.deserialize('json',ser)

但是,我能提供的是:

ser='''[{"pk": 1, "model": "myapp.link",
         "fields": {"uuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                    "sourceuuid": "11111111-2222-3333-4444-555555555555",
                    "targetuuid": "66666666-7777-8888-9999-000000000000"}}]'''
serializer.deserialize('json',ser)
FieldDoesNotExist: Link has no field named u'sourceuuid'

我需要将虚拟字段作为实际字段的原因是因为deserialize需要实际字段。

5 个答案:

答案 0 :(得分:2)

我不确定你到底想要做什么。但请记住,Django模型只是Python对象 - 而Python对象完全是动态的。因此,即使模型上没有定义obj.uuid = whatever字段,也可以uuid完全有效。

答案 1 :(得分:1)

您可以为非物化django模型定义一个外键,用于存储您需要的信息。

为此,在定义了外键(或OnetoOne Key)的新模型中,只需放置

class _meta:
    managed = False

答案 2 :(得分:0)

我不知道这样一个临时领域。这将是很好的:))

但我的建议是:在接收JSON并将其转换为对象的视图中,检查属性。您创建一个对象,只有“真实”属性(不是外键或M2M)。您可以为它们分配任意属性(instance.arbitrary_attribute = something),但是您将无法获得良好的查找机制(Model.objects.filter(...))。创建所有对象后,再次循环遍历对象,并为每个FK查找具有链接UUID的对象,并链接到该对象(使用instance.id)。

答案 3 :(得分:0)

您可以尝试创建普通的python属性,它们不会保存到db。像:

class Link(models.Model):
    sourceuuid = None

答案 4 :(得分:0)

为什么不直接使用UIDS作为主键?

将primary_key设置为True

class Node(models.Model):
    uuid = models.CharField(max_length=32, primary_key=True)
    [...]


class Link(models.Model):
    uuid = models.CharField(max_length=32, primary_key=True)