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

Django表单提交报错:'User' object has no attribute 'get' 求助

问题描述

尝试从用户提交的数据生成PDF(数据基于models.py定义的字段),点击提交按钮后出现报错:

AttributeError at /website/tbt.html
'User' object has no attribute 'get'

相关代码

models.py

tbt_date = models.DateField(
    verbose_name="Date of Creation", default=timezone.now
)
selected_site = models.ForeignKey(
    sites_data, verbose_name="Choose a site", on_delete=models.CASCADE
)
selected_block = models.ForeignKey(
    blocks_list, verbose_name="Choose a block", on_delete=models.SET_NULL, null=True
)
tbt_report_img1 = models.ImageField(
    upload_to="formImages/TBT/", verbose_name="Upload Image 1"
)
tbt_report_img2 = models.ImageField(
    upload_to="formImages/TBT/", verbose_name="Upload Image 2"
)
rt_pdf = models.FileField(upload_to='pdfs/', verbose_name='PDF File', null=True)

views.py

def tbtform(request):
    tbt_form_view = tbt_report_form()
    context = {
        "loggedInUser": request.user,
        "tbt_form":tbt_form_view,
    }
    return context


#@login_required(login_url="user_login")
def generate_tbt_report(request, t_form, selected_form, filename):
    selected_site = t_form.selected_site
    selected_block = t_form.selected_block
    selected_site_data = sites_data.objects.filter(name=selected_site)[0]
    tbt_date = t_form.tbt_date
    print(tbt_date)
    params = {
        "selected_site": selected_site_data,
        "tbt_date": tbt_date,
        "selected_block": selected_block,
        "t": t_form,
        "data": selected_form,
        "loggedInUser": request.user,
    }
    template_path = "website/tbt_report_pdf.html"
    temp_pdf = render_to_pdf(request, template_path, params, filename)
    return temp_pdf

@login_required(login_url="user_login")
def tbt_form(request):
    if request.method == "POST":
        t_form=tbt_report_form(request.user, request.POST, request.FILES)
        t_form.full_clean()
        print("in post")
        if t_form.is_valid():
            print("Valid")
            t_form = t_form.save()
            filename='TBT' + ' ' + str(t_form.tbt_date) + ' ' + str(t_form.selected_block) + '.pdf'
            pdf = generate_tbt_report(request, t_form, filename)
            cv_get = tbt_report.objects.get(id = t_form.id)  
            cv_get.rt_pdf.save(filename, File(BytesIO(pdf.content)))
            print("Saved")
            return pdf
        else:
            print("1")
            print(t_form)
            messages.error(
                request=request, message="Please check all the fields entered!!!"
            )
            return render(request, "website/tbt.html", context=tbtform(request))

    else:
        return render(request, "website/tbt.html", context=tbtform(request))

tbt.html

{% load crispy_forms_tags %}

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

<head>
    
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    
    <link rel="stylesheet" type="text/css"
        href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    
    <style>
        /* .tab {
            display: none;
        } */

        label {
            font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
            text-transform: uppercase;
            padding-top: 18px;
            border-bottom: 5px inset #008000;
            margin-bottom: 15px;
        }

        .form-control-file {
            border: 2px solid #ccc;
            display: inline-block;
            padding: 12px 10px;
            cursor: pointer;
            font-family: monospace;
        }
        .hidden{
            display: none;
        }
    </style>
    <title>VoltAmp - Solar Panacea</title>
</head>

<body>

    <div class="container" style="padding: 5% 12% 10% 12%;">
        <div class="container">
            <img src="{% static 'website/img/logo.jpg' %}" alt="">
        </div>
        <hr>
        <form method="POST" role="form" id='tbt_form' enctype="application/x-www-form-urlencoded"
            data-blocks-url="{% url 'ajax_load_blocks' %}" novalidate>
            {% csrf_token %}
            {% for message in messages %}
            {% if message.tags == "error" %}
            <div class="alert alert-danger">
                {% else %}
                <div class="alert alert-{{ message.tags }}">
                    {% endif %}
                    <a class="close" href="" data-dismiss="alert">×</a>
                    {{ message }}
                </div>
            {% endfor %}

                <div class="container" style="background-color: #FFFF00;padding: 4% ;">
                    <h1 class="text-center"
                        style="font-weight: bold;font-family:'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif">
                        TBT
                    </h1>
                </div>

                <div class="tab">
                    <div class="form-group">
                        {{ tbt_form|crispy }}
                    </div>
                </div>

                <div style="overflow:auto;">

                    <div class="col-sm-12 d-grid gap-2 pt-3">
                        <button type="submit" id="submitBtn" class="btn btn-warning btn-block">Submit</button>
                    </div>

                    <div class="col-sm-12 d-grid gap-2 pt-3">
                        <a href="{% url 'user_logout' %}"><input type="button" id="logoutBtn"
                                class="btn btn-danger btn-block" value="Logout"></a>
                    </div>
                </div>
        </form>
    </div>

            <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js"
                integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4"
                crossorigin="anonymous"></script>

            <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
            
</body>

</html>
错误分析
  1. 表单实例化参数错误:views.py中POST分支创建表单时,错误地将request.user作为第一个参数传入tbt_report_form。Django表单类的第一个参数应为data(POST数据),表单初始化时会尝试调用data.get()方法,而User对象没有该方法,直接触发报错。
  2. 函数调用参数不匹配:generate_tbt_report定义需要4个参数,但调用时只传了3个,导致参数位置错位,后续逻辑可能出现异常。
  3. 表单编码类型错误:表单包含文件上传字段,却使用application/x-www-form-urlencoded编码,无法正确处理文件数据。
解决步骤

1. 修正表单实例化方式

如果表单需要用到当前用户,需在表单类的__init__方法中接收自定义参数:

# forms.py
class tbt_report_form(forms.ModelForm):
    def __init__(self, *args, user=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.user = user
        # 可根据user做字段过滤等操作

    class Meta:
        model = tbt_report
        fields = ['tbt_date', 'selected_site', 'selected_block', 'tbt_report_img1', 'tbt_report_img2']

然后在views.py中正确实例化:

t_form = tbt_report_form(request.POST, request.FILES, user=request.user)

若表单不需要用户参数,直接去掉多余参数:

t_form = tbt_report_form(request.POST, request.FILES)

2. 修正generate_tbt_report函数调用

函数定义中selected_form参数未被实际使用,直接删除该参数:

def generate_tbt_report(request, t_form, filename):
    selected_site = t_form.selected_site
    selected_block = t_form.selected_block
    # 改用first()避免索引错误
    selected_site_data = sites_data.objects.filter(name=selected_site).first()
    if not selected_site_data:
        messages.error(request, "Selected site does not exist")
        return render(request, "website/tbt.html", context=tbtform(request))
    
    tbt_date = t_form.tbt_date
    params = {
        "selected_site": selected_site_data,
        "tbt_date": tbt_date,
        "selected_block": selected_block,
        "t": t_form,
        "loggedInUser": request.user,
    }
    template_path = "website/tbt_report_pdf.html"
    temp_pdf = render_to_pdf(request, template_path, params, filename)
    return temp_pdf

调用时保持参数匹配:

pdf = generate_tbt_report(request, t_form, filename)

3. 修正表单编码类型

在tbt.html的form标签中,设置正确的文件上传编码:

<form method="POST" role="form" id='tbt_form' enctype="multipart/form-data"
    data-blocks-url="{% url 'ajax_load_blocks' %}" novalidate>

4. 额外优化

  • 移除t_form.full_clean(),is_valid()会自动执行表单校验逻辑。
  • 避免使用filter(...)后直接取索引[0],改用first()并处理数据不存在的情况,防止抛出索引错误。
验证修复

完成修改后重新提交表单,确认:

  • 表单可正常校验通过
  • PDF能正确生成并保存至数据库
  • 页面不再抛出AttributeError异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 07:21:34