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

Django:已传递user作为关键字参数,Form对象却无'user'属性?

解决Django TransactionForm实例化的AttributeError问题

错误原因分析

你遇到的AttributeError: 'TransactionForm' object has no attribute 'user',核心问题出在TransactionForm的__init__方法执行顺序和参数处理上:

  1. 你在调用父类__init__方法之前就尝试访问self.user,但此时self还没有被父类初始化,自然没有user属性
  2. 你没有从传入的关键字参数中提取user并将其赋值给self.user
  3. 额外问题:Coin.objects.get(user=...)会返回单个Coin对象,但ModelChoiceField的queryset需要的是QuerySet类型,用get会导致后续赋值出错(如果用户有多个Coin还会抛出MultipleObjectsReturned异常)

修正方案

第一步:修改forms.py的TransactionForm

调整__init__方法的执行顺序,先提取自定义参数,再调用父类初始化,最后处理字段:

class TransactionForm(forms.ModelForm):
    CHOICES = ((1, 'Buy'), (2, 'Sell'),)
    coin = forms.ModelChoiceField(queryset=Coin.objects.all())
    buysell = forms.ChoiceField(choices=CHOICES)
    field_order = ['buysell', 'coin', 'amount', 'trade_price']

    class Meta:
        model = Transactions
        fields = ['buysell', 'coin', 'amount', 'trade_price']  # 用列表更规范,避免集合的无序性

    def __init__(self, *args, **kwargs):
        # 先从kwargs中取出自定义参数,避免父类初始化报错
        self.user = kwargs.pop('user')
        self.coin_price = kwargs.pop('coin_price', None)  # 给个默认值,避免没传时出错
        # 先调用父类的初始化方法
        super().__init__(*args, **kwargs)
        # 用filter获取当前用户的Coin QuerySet,而不是get
        qs_coin = Coin.objects.filter(user=self.user)
        self.fields['coin'].queryset = qs_coin
        # 如果要设置trade_price的初始值,示例如下(根据你的需求调整)
        if self.coin_price:
            self.fields['trade_price'].initial = self.coin_price

第二步:修复views.py的潜在问题

在GET请求的ajax分支里,str(coin.coin)中的coin变量没有定义,需要补充对应的逻辑(比如从请求参数中获取coin标识),否则会抛出NameError:

def add_transaction(request):
    print(request.method)
    print("test1")
    if request.method == "GET":
        if request.is_ajax():
            print("ajax test")
            # 补充获取coin变量的逻辑,比如从GET参数中提取
            coin_id = request.GET.get('coin_id')
            coin_price = None
            if coin_id:
                coin = Coin.objects.get(id=coin_id)
                coin_price = GetCoin(str(coin.coin)).price
            data = {'test': "test1"}
            form = TransactionForm(request.GET, user=request.user, coin_price=coin_price)
            return JsonResponse(data)
        form = TransactionForm(user=request.user)
    elif request.method == "POST":
        print("test2")
        form = TransactionForm(request.POST, user=request.user)
        if form.is_valid():
            print("test3")
            obj = form.save(commit=False)
            obj.user = request.user
            obj.save()
            return HttpResponseRedirect('/myportfolio/')
        else:
            print(form.errors)
    return render(request, 'myportfolio/add_transaction.html', {'form': form})

关键要点总结

  • 自定义表单参数必须在调用父类__init__之前从kwargs中取出,避免父类无法识别这些参数而报错
  • 永远不要在未初始化父类之前访问self的属性
  • ModelChoiceField的queryset必须是QuerySet类型,用filter而不是get来获取多个对象的集合

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:05:19