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

Django CBV获取URL变量报错:name 'self' is not defined

解决Django CreateView中URL参数获取失败及表单预填充隐藏需求

你碰到的NameError: name 'self' is not defined问题很典型——在类定义的顶层直接用self是行不通的,这时候类还没被实例化,self这个实例对象根本不存在,只有在类的实例方法内部(比如dispatch、get_initial这类方法),才能通过self访问实例属性和URL传入的kwargs。

下面是修正后的完整代码,同时满足从URL获取site_id、预填充并隐藏site_data字段、传递上下文的需求:

from django.views.generic.edit import CreateView
from django.contrib.auth.decorators import user_passes_test
from django.utils.decorators import method_decorator
from django.shortcuts import get_object_or_404
from django.urls import reverse_lazy
from .models import SiteSubnets, SiteData

class AddSubnet(CreateView):
    model = SiteSubnets
    template_name = "sites/edit_subnet.html"
    # 先移除site_data,后续通过代码预填充并隐藏
    fields = ['device_data', 'subnet', 'subnet_type', 'circuit', 'vlan_id', 'peer_desc']

    @method_decorator(user_passes_test(lambda u: u.has_perm('config.add_subnet')))
    def dispatch(self, *args, **kwargs):
        # 在请求入口提前获取site_id和对应站点对象,保存为实例属性
        self.site_id = self.kwargs['site_id']
        self.site = get_object_or_404(SiteData, pk=self.site_id)
        return super().dispatch(*args, **kwargs)

    def get_initial(self):
        # 给site_data字段设置预填充值
        initial = super().get_initial()
        initial['site_data'] = self.site
        return initial

    def get_form(self, form_class=None):
        form = super().get_form(form_class)
        # 将site_data字段转为隐藏组件,用户看不到但会自动提交
        form.fields['site_data'].widget = form.fields['site_data'].hidden_widget()
        return form

    def get_success_url(self):
        # 使用实例属性构建跳转URL,避免变量未定义
        return reverse_lazy("sites:site_detail_subnets", args=(self.site_id,))

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 把站点数据传递到模板上下文
        context['SiteID'] = self.site_id
        context['SiteName'] = self.site.location
        context['active_subnets'] = 'class="active"'
        return context

关键改动说明:

  • 把site_id的获取移到dispatch方法:dispatch是所有请求的入口,在这里提前获取URL参数并保存为实例属性,后续所有方法都能直接复用,避免重复查询。
  • 预填充表单字段:通过get_initial方法给site_data设置初始值,表单渲染时会自动带上这个值。
  • 隐藏字段处理:重写get_form方法,将site_data的组件替换为隐藏类型,确保用户看不到但提交时会自动携带该值。
  • 修正变量引用:所有需要用到site_id和站点对象的地方,都改为调用实例属性self.site_id和self.site,彻底解决变量未定义的问题。

另外,模板里可以直接使用上下文传递的{{ SiteID }}和{{ SiteName }}显示站点信息,site_data字段会自动以隐藏域的形式存在于表单中,无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:30:05