Django 抛出重复键值违反唯一约束错误

1 投票
1 回答
40 浏览
提问于 2025-04-14 16:25

我在学习Django框架,里面有一个练习是让你创建一个简单的博客网页应用。这个应用有一些简单的模型和表单,用来处理理论用户在项目数据库中保存的数据。

以下是模型:

from django.db import models


class Blog(models.Model):
    text = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.text

class Post(models.Model):
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
    text = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.text

以下是表单:

from django import forms
from . models import Blog, Post


class BlogForm(forms.ModelForm):
    class Meta:
        model = Blog
        fields = ['text']
        labels = {'text': ''}

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['text']
        labels = {'text': ''}

假设我通过数据库添加了一个博客实例。这样做:

INSERT INTO learning_logs_topic (id, text, date_added)
VALUES
(1, 'A blog #1', now()::timestamptz);

这些数据会出现在Django的管理网站和HTML模板上。几乎是瞬间就能看到,这意味着Django确实知道数据库里新增了数据。但是,当我试图通过管理网站或保存HTML表单来添加一个博客实例时,Django却报错了。

这里我尝试添加一个ID为21的博客实例:

INSERT INTO blogs_blog (id, text, date_added)
VALUES
(21, 'test21', now()::timestamptz);

结果我收到了这个错误:

在 /add_new_blog/ 出现了IntegrityError。

duplicate key value violates unique constraint "blogs_blog_pkey"
DETAIL:  Key (id)=(21) already exists.

我不太明白这是怎么回事。Django从数据库中获取数据并发送到浏览器,但在尝试将数据写入数据库时,它却“看不见”这个ID。

我觉得我需要让Django能够识别数据库中的最新ID。

1 个回答

0

我不太明白这里发生了什么。Django从数据库中获取数据并发送到浏览器,但在尝试将数据写入数据库时,它似乎“看不见”ID。

Django其实并不生成ID,这个工作是数据库自己完成的。在使用PostgreSQL的情况下,通常是通过一个叫做序列 [pgsql-doc]来实现的。如果你手动添加一条记录并指定了id(这通常是个非常糟糕的主意),那么序列就不会更新了。

这个回答展示了如何更新序列,这样从现在开始,它会从22开始生成序列(在这个例子中)。

不过我建议在插入值的时候,不要一开始就指定主键。通常你应该把主键看作一个“黑箱值”。没错,这里是个整数,出于技术原因,但比如说,把两个主键加在一起是没有意义的,所以它只是一个实现细节。

撰写回答