![](/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.