You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django CRUD表单提交后PostgreSQL未写入数据问题咨询

问题背景

PostgreSQL初学者基于Django、Python、HTML、PostgreSQL开发员工信息CRUD功能,填写表单提交后数据未写入PostgreSQL对应数据表,涉及核心代码如下:

templates/employee_register/base.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Employee Register</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
        integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"
        integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
        crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
        integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
        crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.min.js"
        integrity="sha384-VHvPCCyXqtD5DqJeNxl2dtTyhF78xXNXdkwX1CZeRusQfRKp+tA7hAShOK/B/fQ2"
        crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
</head>

<body>
    <div class="container">
        <div class="col-md-10 offset-md-1 mt-5">
            <div class="jumbotron">
                <h1 class="display-4">Employee Register</h1>
                <p class="lead-front-italic">python django project for crud implementation</p>
                <hr class="my-4">
                {% block content %}
                {% endblock content %}
            </div>
        </div>

    </div>

</body>

</html>

templates/employee_register/employee_form.html

{% extends "employee_register/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<form action="" method="post" autocomplete="off">
    {% csrf_token %}
    {{form.first_name|as_crispy_field}}
    {{form.middle_name|as_crispy_field}}
    {{form.last_name|as_crispy_field}}
    {{form.emp_code|as_crispy_field}}
    {{form.department|as_crispy_field}}
    {{form.designation|as_crispy_field}}
    {{form.location|as_crispy_field}}
    {{form.status|as_crispy_field}}
    {{form.date_of_birth|as_crispy_field}}
    {{form.date_of_joining|as_crispy_field}}
    {{form.gender|as_crispy_field}}
     <button type="submit" class="btn btn-success">
        <i class="fa-solid fa-database"></i>Submit
     </button>
</form>
{% endblock content %}

templates/employee_register/employee_register.html

{% extends "employee_register/base.html" %}

{% block content %}
<p>we'll show list of employee from the table</p>
{% endblock content %}

models.py

from django.db import models

class Position(models.Model):
    title = models.CharField(max_length=50)

    def __str__(self):
        return self.title

class Employee(models.Model):
    first_name=models.CharField(max_length=100)
    middle_name=models.CharField(max_length=100)
    last_name=models.CharField(max_length=100)
    emp_code=models.CharField(max_length=3)
    department=models.CharField(max_length=100)
    designation=models.ForeignKey(Position,on_delete=models.CASCADE)
    location = models.CharField(max_length=20)
    date_of_birth=models.DateField()
    date_of_joining=models.DateField()
    gender = models.CharField(max_length=6)
    status = models.CharField(max_length=10)

views.py

from django.shortcuts import render,redirect
from .forms import EmployeeForm

def employee_list(request):
    return render(request,"employee_register/employee_list.html")

def employee_form(request):
    if request.method == "GET":
        form = EmployeeForm()
        return render(request,"employee_register/employee_form.html",{'form':form})

    else:
        form = EmployeeForm(request.POST)
        if form.is_valid():
            form.save()
        return redirect('/employee/list')
排查思路与解决方案

按以下顺序从易到难排查:

  • 第一步:确认数据库配置与模型迁移正常
    首先检查项目settings.py中DATABASES配置是否正确指向目标PostgreSQL数据库,核对主机地址、端口、库名、用户名、密码无拼写错误。
    确认已经执行过模型迁移命令,且执行过程无报错:
    python manage.py makemigrations
    python manage.py migrate
    
    迁移完成后直接连接PostgreSQL,检查库中是否存在employee_position、employee_employee两张表,确认表结构和模型字段一致。
  • 第二步:修复视图逻辑缺陷,暴露表单校验错误
    这是当前代码最核心的问题:现有POST处理逻辑中,只要表单校验不通过,会直接跳转列表页,既不执行保存,也不向前端返回错误信息,用户完全感知不到校验失败,会误以为提交成功但数据没存上。
    修改employee_form视图的POST分支逻辑,校验失败时返回带错误提示的表单页,修改后代码如下:
    def employee_form(request):
        if request.method == "GET":
            form = EmployeeForm()
            return render(request,"employee_register/employee_form.html",{'form':form})
        else:
            form = EmployeeForm(request.POST)
            if form.is_valid():
                form.save()
                return redirect('/employee/list')
            # 校验失败,返回表单页展示错误
            return render(request,"employee_register/employee_form.html",{'form':form})
    
    修改后再次提交表单,如果字段不符合规则,页面会直接显示crispy forms渲染的具体错误,常见校验失败原因包括:
    • emp_code字段最大长度为3,输入超过3个字符
    • designation外键字段传入了不存在的Position ID
    • 日期字段输入格式不符合Django日期解析规则
    • gender、status、location等字段输入长度超过模型定义的max_length
  • 第三步:检查表单类配置正确性
    核对forms.py代码,确认EmployeeForm为ModelForm,且字段配置正确,不要遗漏必填字段、不要错误设置字段排除规则。参考正确写法:
    from django import forms
    from .models import Employee
    
    class EmployeeForm(forms.ModelForm):
        class Meta:
            model = Employee
            fields = '__all__' # 或显式列出所有需要提交的字段
    
    额外确认外键字段designation的查询集配置正常,默认会加载所有Position数据作为可选项,如果自定义了queryset要确保包含用户选择的职位选项。
  • 第四步:确认数据库权限与路由配置
    检查settings中配置的PostgreSQL账号,对目标数据库拥有INSERT写入权限,避免只读账号导致写入失败。
    核对urls.py中的路由规则,确认表单提交的路径正确映射到employee_form视图,没有请求到错误的接口。可以在视图POST分支第一行加打印日志print("收到表单提交", request.POST),启动开发服务器后提交,看控制台是否输出日志,确认请求正常到达视图。
  • 第五步:核对模板文件名映射
    现有employee_list视图渲染的模板为employee_list.html,注意核对文件名不要拼写错误,避免跳转404影响判断。

内容的提问来源于stack exchange,提问作者Ameya Potdar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 23:01:39