首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django无法使用多个主键修改Server中的行

Django无法使用多个主键修改Server中的行
EN

Stack Overflow用户
提问于 2021-06-09 14:46:59
回答 1查看 143关注 0票数 1

我正在使用Django 3.0DjangoRestFramework 3.12django-mssql-backend 2.8.1来构建当前桌面应用程序的webapp版本,该应用程序可以将所有内容存储在遗留的MS数据库中。因此,我仅限于不改变已经存在的表结构的数据库修改。

我使用内置的遗留数据库模型生成器构建了Django模型,然后自己进行了最后的修改。我一直在遵循教程来构建一个API来处理数据,每个人似乎都建议使用DRF。我的所有视图都使用ListAPIViewRetrieveAPIViewRetrieveUpdateAPIView。现在,当我试图构建部分API以允许我在其中一个表中更改设置时,我在插入一个重复的键值时遇到了一个错误。

数据库表:

代码语言:javascript
复制
dbo.systemDateTimeSettings
  - LocationID (PK, FK, int, not null)  
  - Setting (PK, nvarchar(50), not null)
  - Value (datetime, null)

模型:

代码语言:javascript
复制
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'),)

序列化程序:

代码语言:javascript
复制
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)

网址:

代码语言:javascript
复制
path('locations/<int:location_id>/settings/datetime/<str:setting>/update', DatetimeSettingsUpdate.as_view(), name='datetime-settings-update'),

视图:

代码语言:javascript
复制
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)

我得到的错误是:

代码语言:javascript
复制
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)")

我从中看到的是,真正的根本问题是Server数据库使用LocationID并将两者设置为主键,但是Django不允许多个主键。

当我指向那个URL时,我可以拉下一个实例。但是,当我去更改这个值时,我遇到了一个关于插入一个重复键的错误;这是不寻常的,因为我不是在创建一个新的键值,而是试图修改一个先前存在的键值。

我在这里查看过其他的例子,其中人们在数据库中有多个主键,比如这里这里这里,但是他们似乎都提到使用unique_together,我已经提到了,但是没有提到如何使用这个约束。

有什么办法解决这个问题吗?还是我需要以某种方式修改遗留数据库?

编辑:i在Server中编写了aaaaaSystemDateTimeSettings_PK约束脚本,并得到:

代码语言:javascript
复制
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

我尝试删除约束(本地复制-不要恐慌),然后尝试更新页面。它完成了,但覆盖了所有具有相同SettingValueLocationID,具有相同的setting名称和新的value。它似乎只是为了防止LocationIDSetting重叠在一起。

为了让我清楚地知道我想做什么,下面是我的桌子之前的样子:

修改前

下面是我想通过更新页面所做的事情:

在修改数据库之后

EN

回答 1

Stack Overflow用户

发布于 2021-06-09 14:51:11

您的错误告诉您,您正在尝试添加/更新数据库中已经存在的带有unique_together = (('location_id', 'setting'),)约束的models.py中的行,以避免这种情况,您必须确保正在添加/更新的值在数据库中不存在。在您的例子中,错误告诉您location_id=3setting='Next Measurement'已经存在。

要解决这个问题,可以删除约束并运行迁移,或者在添加/更新这些字段时处理Integrity错误。

因为你说

LocationID和将两者都设置为主键

您需要更新设置字段,使其也是唯一的。

代码语言:javascript
复制
setting = models.CharField(db_column='Setting', max_length=50, unique=True)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67906540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档