我正在研究一种方法来序列化数据库A中的部分数据并在数据库B中对其进行反序列化(在不同的安装之间进行一种保存/恢复)并且我已经看过Django natural keys避免由于ID重复而导致的问题。
唯一的问题是我应该为我的所有模型添加自定义管理器和新方法。有没有办法让Django通过查看unique=True
或unique_togheter
字段自动生成自然键?
答案 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()方法编辑模型以扩展客户基础模型。这对您的数据库表结构和旧保存数据没有任何副作用,除非您更新一些旧行。如果您有旧数据,请尝试对您的所有记录进行虚假更新。