Python 如何使用Django表单';获取\u field()方法的\u initial\u?

Python 如何使用Django表单';获取\u field()方法的\u initial\u?,python,django,Python,Django,我有两种型号公司和包装,定义如下: class Company(models.Model): default_package = models.OneToOneField( Package, blank=True, null=True, related_name='default_for_%(class)s') class Package(models.Model): company = models.Forei

我有两种型号
公司
包装
,定义如下:

class Company(models.Model):
    default_package = models.OneToOneField(
        Package,
        blank=True,
        null=True,
        related_name='default_for_%(class)s')


class Package(models.Model):
    company = models.ForeignKey('lucy_web.Company')
其中
lucy\u web
是应用程序的名称。因此,
公司
之间存在多对一关系,此外,
公司
和其
默认包
之间存在一对一关系

我正在为
Package
对象制作一个
ModelForm
,它的简化版本是

class PackageForm(forms.ModelForm):
    class Meta:
        model = Package
        fields = [
            'is_default',
        ]

    is_default = forms.BooleanField(initial=True, required=False)

    def save(self, *args, **kwargs):
        package = super().save(*args, **kwargs)
        if self.cleaned_data['is_default']:
            package.company.default_package = package
            package.company.save()
        return package
因此,当
为默认值时
设置为
True
,包将被设置为其公司的默认包

问题在于,此表单在通用
CreateView
UpdateView
中都使用,并且在
UpdateView
中,即使包不是默认包,
是默认的
仍然设置为
True
。这将使用户很容易在不经意间将包更改为默认值,而实际上他们只是想更改另一个字段

我想将
首字母
设置为默认值
,这样,对于未绑定表单,它是
真的
,对于绑定表单,它是
真的
,只有当
公司的默认值
时。我试图将其添加到
\uuuu init\uuuu()
,如下所示:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    if self.instance and self.instance.default_for_company:
        self.initial['is_default'] = True
但是,不幸的是,对于非默认的包,这会导致
RelatedObjectDoesNotExist
错误:

File "/Users/kurtpeek/Documents/Dev/lucy/lucy-web/dashboard/forms/packages.py" in __init__
  60.         if self.instance and self.instance.default_for_company:

File "/Users/kurtpeek/Documents/Dev/lucy/lucy-web/venv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py" in __get__
  407.                     self.related.get_accessor_name()

Exception Type: RelatedObjectDoesNotExist at /dashboard/packages/55
Exception Value: Package has no default_for_company.

另外,重写
\uuuu init\uuuu()
似乎有点“黑客”,而且该方法似乎就是为此而设计的。这是我可以为我的
PackageForm
定义的东西,以这种方式“动态”获取字段的初始值吗?(从文档中我不清楚如何在这种情况下应用它)。

您覆盖
\uuuuu init\uuuu
方法的方法在我看来是可行的。使用
hasattr
避免出现
relatedObjectsDoesNotExist
异常

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    if self.instance and hasattr(self.instance, 'default_for_company'):
        self.initial['is_default'] = True

我以前没有为字段使用过
get\u initial\u
。看起来您可以执行以下操作:

def get_initial_for_field(self, field, field_name):
    if field_name == 'is_default':
        return bool(self.instance and hasattr(self.instance, 'default_for_company'))
    return super().get_initial_for_field(field, field_name)

在我看来,您重写
\uuuu init\uuu
方法的方法是可行的。使用
hasattr
避免出现
relatedObjectsDoesNotExist
异常

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    if self.instance and hasattr(self.instance, 'default_for_company'):
        self.initial['is_default'] = True

我以前没有为字段使用过
get\u initial\u
。看起来您可以执行以下操作:

def get_initial_for_field(self, field, field_name):
    if field_name == 'is_default':
        return bool(self.instance and hasattr(self.instance, 'default_for_company'))
    return super().get_initial_for_field(field, field_name)

后一种方法似乎有效,谢谢!我唯一剩下的问题是,对于
CreateView
(新软件包的表单),
是默认的
初始值
没有设置为
True
。我注意到在这种情况下,实际上,
self.initial
是一个空字典,所以我可以对它进行特殊处理,但有没有更好的方法?
get_initial_for_field
在我尝试它时,与
CreateView
配合得很好,所以您只需要确保在方法中使用了正确的逻辑。检查
self.instance.pk
是检查您是否正在创建或更新模型实例的典型方法。后一种方法似乎有效,谢谢!我唯一剩下的问题是,对于
CreateView
(新软件包的表单),
是默认的
初始值
没有设置为
True
。我注意到在这种情况下,实际上,
self.initial
是一个空字典,所以我可以对它进行特殊处理,但有没有更好的方法?
get_initial_for_field
在我尝试它时,与
CreateView
配合得很好,所以您只需要确保在方法中使用了正确的逻辑。检查
self.instance.pk
是检查您是否正在创建或更新模型实例的典型方法。请注意,您的措辞“对于未绑定表单为真,对于绑定表单为真”没有真正的意义。初始数据仅用于未绑定的
表单。也许您的意思是创建/更新实例。另一个选项是为您的
UpdateView
覆盖
get_initial()
。请注意,您的措辞“对于未绑定表单和绑定表单都是真的”没有真正的意义。初始数据仅用于未绑定的
表单。也许您的意思是创建/更新实例。另一个选项是为您的
UpdateView
覆盖
get_initial()