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

如何解决Django模板中保存外键时的ValueError错误?

解决Django外键字段赋值的ValueError问题

问题根源

通过HTML的select提交数据时,后端收到的是Category的ID(字符串类型),但BookDetails的category外键字段要求传入Category模型的实例,直接将字符串ID赋值给外键字段就会触发ValueError。

解决步骤

以下结合常规代码结构给出解决方案,可根据你的实际代码调整:

1. 确认模型结构(models.py)

先确保模型定义正确:

from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class BookDetails(models.Model):
    title = models.CharField(max_length=200)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

2. 修改视图逻辑(views.py)

有两种简洁的处理方式:

方法一:通过ID获取Category实例后赋值

from django.shortcuts import render, redirect
from .models import BookDetails, Category

def add_book(request):
    if request.method == 'POST':
        title = request.POST.get('title')
        category_id = request.POST.get('category')
        # 根据ID获取对应分类实例
        category = Category.objects.get(id=category_id)
        # 创建并保存图书记录
        book = BookDetails(title=title, category=category)
        book.save()
        return redirect('book_list')
    # GET请求时传递所有分类给模板渲染下拉框
    categories = Category.objects.all()
    return render(request, 'add_book.html', {'categories': categories})

方法二:直接使用category_id赋值(更高效)

Django会为外键字段自动生成{外键字段名}_id属性,直接赋值ID即可完成关联:

def add_book(request):
    if request.method == 'POST':
        title = request.POST.get('title')
        category_id = request.POST.get('category')
        # 无需获取实例,直接通过category_id赋值
        book = BookDetails(title=title, category_id=category_id)
        book.save()
        return redirect('book_list')
    categories = Category.objects.all()
    return render(request, 'add_book.html', {'categories': categories})

3. 确保HTML模板的select字段正确(add_book.html)

下拉框的option值必须是Category的ID,不能是名称或其他字符串:

<form method="POST">
    {% csrf_token %}
    <label for="title">书名:</label>
    <input type="text" id="title" name="title">
    
    <label for="category">分类:</label>
    <select id="category" name="category">
        {% for category in categories %}
            <option value="{{ category.id }}">{{ category.name }}</option>
        {% endfor %}
    </select>
    
    <button type="submit">保存</button>
</form>

额外优化建议

如果使用Django的ModelForm,会自动处理外键的类型转换,无需手动编写字段逻辑,更不易出错:

# forms.py
from django import forms
from .models import BookDetails

class BookForm(forms.ModelForm):
    class Meta:
        model = BookDetails
        fields = ['title', 'category']

视图中使用表单:

def add_book(request):
    if request.method == 'POST':
        form = BookForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('book_list')
    else:
        form = BookForm()
    return render(request, 'add_book.html', {'form': form})

模板中直接渲染表单:

<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">保存</button>
</form>

内容的提问来源于stack exchange,提问作者Mahfujul Hasan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 13:36:14