2009-12-12 86 views
2

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

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

如果源有值的2的ID和目标具有值12的ID,这将被序列化到JSON作为这样的:

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

然而,因为在这种情况下,我们不知道的源和目标的数据库ID,可能是因为他们尚未设置,我所能做的最好的是通过在UUID是这样的:

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

不幸的是,th当我拨打serializers.deserialize的数据时,引发了FieldDoesNotExist: Link has no field named u'sourceuuid'的例外。

我想找到一种方法,我可以通过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需要实际的领域。

回答

1

你可以定义一个外键给非物化django模型,它存储你需要的信息。

要做到这一点,在新的模型的外键(或OnetoOne密钥)的定义,只需将

class _meta: 
    managed = False 
+0

这是最接近的,但不是你所期望的。一个到非物化Django模型的ForeignKey仍然在引用表中添加一列。但是,如果我使用'sourceuuid'和'targetuuid'作为新字段创建一个完整的非物化子类,我可以到某处。我在一个新的'LinkJSON'类中反序列化,然后映射UUID,然后将这些字段复制到'Link'类。它不漂亮,但它有点不错。如果Python有一个简单的方法将类型转换为基类,那将会更好。 – Pridkett 2009-12-12 14:50:07

+0

我接受这个答案,因为它最接近我想要做的。我不得不做一些时髦的子类化,然后创建一个JSONSerializer的子类来处理所有事情,但它现在起作用了。不幸的是,它成为一个非常具体的解决方案,所以我不能将它的全部内容发布到StackOverflow。 – Pridkett 2010-01-04 19:48:05

0

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

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

+0

我试图避免去用JSON所有muckity渣土。这是我可以在代码中引入错误和问题的另一个地方。它会工作,但它是一个混乱的最后手段。 – Pridkett 2009-12-12 14:53:28

0

你可以尝试创建普通的python属性,它们不会保存到数据库。喜欢:

class Link(models.Model): 
    sourceuuid = None 
+0

查看我的更新以获得澄清。 'deserializer'方法拒绝处理任何不是'Field'的数据。所以这个方法会抛出一个异常。 – Pridkett 2009-12-12 14:51:00

2

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

+0

我已经更新了一些更详细的问题。我需要它是一个实际的'Field',否则'deserialize'会抛出一个异常。 – Pridkett 2009-12-12 14:51:47

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) 
+0

我已经想过,如果我找不到另一种方式,那就是我可能做的。但是,UUID在数据库中占用更多的空间,并且比索引搜索和搜索要慢。 – Pridkett 2009-12-12 18:16:38

+0

这是很不清楚你想要做什么..也许如果你带来更多的细节关于你的任务会有一个很好的解决方案 – 2009-12-12 18:47:27

相关问题