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

Django删除钱包报错ValueError:Field 'id'期望数字却获'Btc'

Django删除钱包地址时ValueError错误排查

在Django模板展示钱包地址列表,点击删除按钮时触发错误:ValueError: Field 'id' expected a number but got 'Btc',但手动在删除视图URL中输入地址ID可成功删除。以下是错误栈及相关代码的分析和解决方案:

错误栈

Traceback (most recent call last):
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\fields\__init__.py", line 2018, in get_prep_value
    return int(value)

The above exception (invalid literal for int() with base 10: 'Btc') was the direct cause of the following exception:
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\contrib\auth\decorators.py", line 23, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "C:\Users\admin\Documents\Django\crypto\dashboard\views.py", line 275, in del_wallet
    wallet.delete()
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\base.py", line 1137, in delete
    return collector.delete()
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\deletion.py", line 475, in delete
    query.update_batch(
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\sql\subqueries.py", line 78, in update_batch
    self.get_compiler(using).execute_sql(NO_RESULTS)
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\sql\compiler.py", line 1819, in execute_sql
    cursor = super().execute_sql(result_type)
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\sql\compiler.py", line 1382, in execute_sql
    sql, params = self.as_sql()
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\sql\compiler.py", line 1785, in as_sql
    val = field.get_db_prep_save(val, connection=self.connection)
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\fields\related.py", line 1146, in get_db_prep_save
    return self.target_field.get_db_prep_save(value, connection=connection)
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\fields\__init__.py", line 925, in get_db_prep_save
    return self.get_db_prep_value(value, connection=connection, prepared=False)
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\fields\__init__.py", line 2703, in get_db_prep_value
    value = self.get_prep_value(value)
  File "C:\Users\admin\Documents\Django\env\lib\site-packages\django\db\models\fields\__init__.py", line 2020, in get_prep_value
    raise e.__class__(

Exception Type: ValueError at /dashboard/wallet/2/delete/
Exception Value: Field 'id' expected a number but got 'Btc'.

相关代码

views.py

@login_required
def wallet(request):
    user = request.user
    wallet=Wallet(user=user)
    object_list = Wallet.objects.filter(user=user)
    # Paginator
    paginator = Paginator(object_list, 2) 
    page = request.GET.get('page')
    try:
        ref = paginator.page(page)
    except PageNotAnInteger:
        ref = paginator.page(1)
    except EmptyPage:
        ref = paginator.page(paginator.num_pages)    
    if request.method == 'POST':
        if 'add' in request.POST:
            form = WalletForm(request.POST, instance=wallet)
            if form.is_valid():
                form.save()
                messages.success(request, ("New wallet address successfully added."))
                return redirect("dashboard:wallet")
    else:
        form = WalletForm(instance=user)
    context = {
        'form': form,
        'ref': ref,
    }
    return render(request, 'dashboard/wallet.html', context)


@login_required
def del_wallet(request, pk):
    wallet = get_object_or_404(Wallet, id=pk)
    wallet.delete()
    return redirect("dashboard:wallet")

urls.py

urlpatterns = [
    path('wallet', wallet, name="wallet"),
    path('wallet/<str:pk>/delete/', del_wallet, name="del_wallet"),
]

wallet.html

<h3 class="h5 text-primary pt-1 pt-lg-3 mt-4">Available Wallets</h3>
<div class="table-responsive">
    <table class="table table-dark table-striped">
        <thead>
            <tr>
            <th>SN</th>
            <th>Type</th>
            <th>Address</th>
            <th>Delete</th>
            </tr>
        </thead>
        <tbody>
            {% for i in ref %}
                <tr>
                    <td style="line-height: 1.3; padding-top: 1.6em;">{{ forloop.counter }}</td>
                    <td style="padding-top: 20px;">{{ i.get_type_display }}</td>
                    <td style="padding-top: 20px;">{{ i.address }}</td>
                    <td class="view" data-bs-toggle="modal" data-bs-target="#wallet{{ i.pk }}">
                        <a style="text-decoration: none;" href="#wallet{{ i.pk }}">
                            Delete
                        </a>
                    </td>
                </tr>
                <!-- DELETE MODAL -->
                <div class="modal fade" id="wallet{{ i.pk }}" tabindex="-1" role="dialog" style="margin-top: 10em;">
                    <div class="modal-dialog modal-sm" role="document">
                        <div class="modal-content" style="background: #141822;">
                            <div class="modal-body">
                                <h6>Confirm Delete</h6>
                                <p>Are you sure you want to delete 
                                    <span style="color: rgb(10, 223, 165);">
                                        {{ i.type }} - {{ i.address }}
                                    </span> wallet?
                                </p>
                                    <button type="submit" class="btn btn-primary btn-sm w-100">
                                        <a href="/dashboard/wallet/{{ i.pk }}/delete/" style="text-decoration: none;">
                                            Confirm
                                        </a>
                                    </button><br>
                                    <button type="button" class="btn btn-warning btn-sm w-100 mt-2" data-bs-dismiss="modal">
                                       Close
                                    </button>
                            </div>
                        </div>
                    </div>
                </div>
            {% empty %}
                <tr>
                    <td>You haven't added a wallet address yet.</td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
</div>

models.py

class Wallet(models.Model):
    wallet = (
        ('Btc', 'Bitcoin'), 
        ('Eth', 'Ethereum'), 
        ('Trc20', 'Tether-UDST'), 
        ('Ltc', 'Litecoin') 
)
    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    type = models.CharField(choices=wallet, default='Btc') 
    address = models.CharField(max_length=80)

错误原因分析

  1. 级联删除配置错误:错误栈显示在执行wallet.delete()时,Django尝试将某个外键字段的值设置为字符串'Btc',但该字段需要整数类型的ID。这说明项目中存在其他关联到Wallet模型的模型(如交易记录模型),其外键字段的on_delete参数被错误设置为models.SET('Btc'),而非合法的选项(如SET_NULL、CASCADE等)。

  2. 前端按钮类型干扰:模板中确认删除的按钮使用了type="submit",会触发页面上的表单提交(如添加钱包的表单),可能导致请求参数混乱,干扰正常的删除跳转。

  3. URL参数类型不严谨:urls.py中删除路径的pk参数使用<str:pk>,而Wallet的id是整数类型,容易接受非整数的非法参数。

解决方案

1. 修复关联模型的级联删除配置

检查所有关联Wallet的外键字段,修正on_delete参数:

  • 如果允许外键为NULL:
    wallet = models.ForeignKey(Wallet, on_delete=models.SET_NULL, null=True)
    
  • 如果需要设置默认钱包,需传入可调用对象返回合法的ID:
    def get_default_wallet_id():
        return Wallet.objects.get_or_create(type='Btc', user=request.user)[0].id  # 按需调整用户逻辑
    wallet = models.ForeignKey(Wallet, on_delete=models.SET(get_default_wallet_id), default=get_default_wallet_id)
    

2. 修改前端按钮类型

将模态框中的确认按钮改为type="button",或直接使用<a>标签替代按钮,避免触发表单提交:

<!-- 方式1:修改按钮类型 -->
<button type="button" class="btn btn-primary btn-sm w-100">
    <a href="/dashboard/wallet/{{ i.pk }}/delete/" style="text-decoration: none;">
        Confirm
    </a>
</button>

<!-- 方式2:直接使用a标签 -->
<a href="/dashboard/wallet/{{ i.pk }}/delete/" class="btn btn-primary btn-sm w-100" style="text-decoration: none;">
    Confirm
</a>

3. 严谨设置URL参数类型

将urls.py中的删除路径参数改为<int:pk>,限制仅接受整数ID:

path('wallet/<int:pk>/delete/', del_wallet, name="del_wallet"),

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 06:45:32