![](/img/trans.png)
[英]Reference one foreign key to multiple primary keys in SQL Server 2014
[英]Django unable to modify a row in SQL Server with multiple primary keys
我正在使用Django 3.0
、 DjangoRestFramework 3.12
和django-mssql-backend 2.8.1
來構建當前桌面應用程序的 webapp 版本,該版本將所有內容存儲在舊版 MS SQL 服務器數據庫中。 因此,我僅限於不會改變已經存在的表結構的數據庫修改。
我使用內置的遺留數據庫模型生成器構建了我的 Django 模型,然后自己進行了最終修改。 我一直在按照教程構建一個 API 來處理數據,每個人似乎都建議使用 DRF。 我的所有視圖都使用ListAPIView
、 RetrieveAPIView
和RetrieveUpdateAPIView
。 現在,當我嘗試構建 API 的一部分以允許我更改其中一個表中的設置時,我遇到了關於插入重復鍵值的錯誤。
數據庫表:
dbo.systemDateTimeSettings
- LocationID (PK, FK, int, not null)
- Setting (PK, nvarchar(50), not null)
- Value (datetime, null)
Model:
class SystemDatetimeSettings(models.Model):
location_id = models.OneToOneField(Locations, models.DO_NOTHING, db_column='LocationID', primary_key=True)
setting = models.CharField(db_column='Setting', max_length=50)
value = models.DateTimeField(db_column='Value', blank=True, null=True)
def get_api_url(self, request=None):
return reverse("api:datetime-settings-update",
kwargs={
'location_id': int(self.location_id.location_id),
'setting': self.setting
},
request=request)
class Meta:
managed = False
db_table = 'SystemDateTimeSettings'
unique_together = (('location_id', 'setting'),)
序列化器:
class SystemDatetimeSettingsSerializer(serializers.ModelSerializer):
url = serializers.SerializerMethodField(read_only=True)
class Meta:
model = SystemDatetimeSettings
fields = [
'url',
'location_id',
'setting',
'value'
]
read_only_fields = [
'location_id',
'setting',
]
def get_url(self, obj):
request = self.context.get("request")
return obj.get_api_url(request=request)
Url:
path('locations/<int:location_id>/settings/datetime/<str:setting>/update', DatetimeSettingsUpdate.as_view(), name='datetime-settings-update'),
看法:
class DatetimeSettingsUpdate(RetrieveUpdateAPIView):
lookup_field = 'setting'
serializer_class = SystemDatetimeSettingsSerializer
permission_classes = [permissions.IsAuthenticated]
# queryset = SystemDatetimeSettings.objects.all()
def get_object(self):
location_id = self.kwargs.get('location_id')
setting = self.kwargs.get('setting')
return get_object_or_404(SystemDatetimeSettings, location_id=location_id, setting=setting)
我得到的錯誤是:
IntegrityError at /api/locations/3/settings/datetime/Next Measurement/update
('23000', "[23000] [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Violation of PRIMARY KEY constraint 'aaaaaSystemDateTimeSettings_PK'. Cannot insert duplicate key in object 'dbo.SystemDateTimeSettings'. The duplicate key value is (3, Next Measurement). (2627) (SQLExecDirectW); [23000] [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]The statement has been terminated. (3621)")
我從所有這些中讀到的是,真正的潛在問題是 SQL 服務器數據庫正在使用 LocationID 和 Setting 兩者作為主鍵,但 Django 不允許多個主鍵。
當我前往那個 URL 時,我能夠拉下一個實例。 但是當我 go 更改值時,我只是遇到了關於插入重復鍵的錯誤; 這是不尋常的,因為我沒有創建一個新的鍵值,只是試圖修改一個預先存在的鍵值。
我在此處查看了人們在數據庫中有多個主鍵的其他實例,例如此處、 此處和此處,但他們似乎都提到了使用unique_together
,我有,但沒有提到如何使用那個約束。
有沒有辦法解決這個問題? 還是我需要以某種方式修改舊數據庫?
編輯:我在 SQL 服務器中編寫了aaaaaSystemDateTimeSettings_PK
約束並得到:
ALTER TABLE [dbo].[SystemDateTimeSettings] ADD CONSTRAINT [aaaaaSystemDateTimeSettings_PK] PRIMARY KEY CLUSTERED
(
[LocationID] ASC,
[Setting] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
我嘗試刪除約束(本地副本 - 不要驚慌),然后嘗試更新頁面。 它通過但覆蓋了具有相同LocationID
和相同setting
名稱和新value
的每個Setting
和Value
。 似乎它只是為了防止LocationID
和Setting
重復。
只是為了讓我對我想做的事情一清二楚,這就是我的桌子事先看起來的樣子:
這是我希望能夠對更新頁面執行的操作:
您的錯誤是告訴您您正在嘗試添加/更新數據庫中的一行,該行已經存在於models.py
中的unique_together = (('location_id', 'setting'),)
約束為避免這種情況,您必須確保您正在添加/更新的值在數據庫中尚不存在。 在您的情況下,錯誤告訴您location_id=3
和setting='Next Measurement'
已經存在。
要解決此問題,請刪除約束並運行遷移,或者在添加/更新這些字段時處理Integrity
錯誤。
既然你說
LocationID 和將兩者都設置為主鍵
您還需要將設置字段更新為唯一。
setting = models.CharField(db_column='Setting', max_length=50, unique=True)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.