自动生成自然键

时间:2010-12-21 09:02:44

标签: django django-models natural-key

我正在研究一种方法来序列化数据库A中的部分数据并在数据库B中对其进行反序列化(在不同的安装之间进行一种保存/恢复)并且我已经看过Django natural keys避免由于ID重复而导致的问题。

唯一的问题是我应该为我的所有模型添加自定义管理器和新方法。有没有办法让Django通过查看unique=Trueunique_togheter字段自动生成自然键?

4 个答案:

答案 0 :(得分:3)

请注意这个答案与Django无关,但希望能给你另一种思考方式。

您没有提及您的数据库,但是,在SQL Server中,您可以使用BINARY_CHECKSUM()关键字为行中保存的数据提供唯一值。可以将其视为对行中所有字段的哈希。 该校验和方法可用于通过检查本地行校验和<>来更新数据库。远程行校验和。

下面的SQL将从远程数据库更新本地数据库。它不会插入新行,因为您使用insert ... where id > @MaxLocalID

SELECT  delivery_item_id, BINARY_CHECKSUM(*) AS bc
INTO    #DI
FROM    [REMOTE.NETWORK.LOCAL].YourDatabase.dbo.delivery_item di


SELECT  delivery_item_id, BINARY_CHECKSUM(*) AS bc
INTO    #DI_local
FROM    delivery_item di

-- Get rid of items that already match
DELETE  FROM #DI_local
WHERE   delivery_item_id IN (SELECT l.delivery_item_id
                             FROM   #DI x, #DI_local l
                             WHERE  l.delivery_item_id = x.delivery_item_id
                             AND l.bc = x.bc)

DROP TABLE #DI

UPDATE  DI
SET     engineer_id = X.engineer_id,
        ... -- Set other fields here
FROM    delivery_item DI,
        [REMOTE.NETWORK.LOCAL].YourDatabase.dbo.delivery_item x,
        #DI_local L
WHERE   x.delivery_item_id = L.delivery_item_id
        AND DI.delivery_item_id = L.delivery_item_id

DROP TABLE #DI_local

要使上述工作正常,您需要在本地数据库和远程数据库之间使用链接服务器:

-- Create linked server if you don't have one already 
IF NOT EXISTS ( SELECT  srv.name
                FROM    sys.servers srv
                WHERE   srv.server_id != 0
                        AND srv.name = N'REMOTE.NETWORK.LOCAL' ) 
    BEGIN
        EXEC master.dbo.sp_addlinkedserver @server = N'REMOTE.NETWORK.LOCAL',
        @srvproduct = N'SQL Server'

        EXEC master.dbo.sp_addlinkedsrvlogin
        @rmtsrvname = N'REMOTE.NETWORK.LOCAL',
        @useself = N'False', @locallogin = NULL,
        @rmtuser = N'your user name',
        @rmtpassword = 'your password'
    END
GO

答案 1 :(得分:1)

在这种情况下,您应该使用GUID作为密钥。数据库可以自动为您生成这些。 Google uniqueidentifier 。我们有50多个仓库都远程插入数据,并使用SQL Server复制将数据发送到我们的主数据库。它们都使用GUID作为主键,因为它保证是唯一的。它运作得很好。

答案 2 :(得分:1)

我的解决方案与自然键无关,但使用picke/unpickle。 这不是最有效的方法,但它很容易适应您的代码。我不知道它是否适用于复杂的数据库结构,但如果不是这种情况,请尝试一下!

连接到db A时:

import pickle
records_a = your_model.objects.filter(...) 
f = open("pickled.records_a.txt", 'wb')
pickle.dump(records_a, f) 
f.close()

然后移动文件,当连接到db B时运行:

import pickle 
records_a = pickle.load(open('pickled.records_a.txt'))
for r in records_a:
    r.id = None
    r.save()

希望这有帮助

答案 3 :(得分:0)

通过扩展models.Model类来创建自定义基本模型,并在其中编写通用管理器,然后使用.save()方法编辑模型以扩展客户基础模型。这对您的数据库表结构和旧保存数据没有任何副作用,除非您更新一些旧行。如果您有旧数据,请尝试对您的所有记录进行虚假更新。