Django - 在表单窗口小部件类中获取实例pk

时间:2011-03-30 15:29:06

标签: django-models django-forms

我创建了一个自定义小部件,其中包含指向某些ajax功能的链接。为了使其工作,我需要传递我正在编辑的实例的pk。似乎小部件无法访问当前的模型实例(有充分理由!)所以我想知道如何获取这些信息?我是否必须从uri获得它,或者是否有一种方便的方法我会忽略它会给我我需要的东西。

由于

3 个答案:

答案 0 :(得分:4)

您可以覆盖窗口小部件的__init__方法并将其传递给窗体实例。从表单实例中,如果存在,则可以获取pk。

在这个答案中,他们将form_instance绑定到表单的 init 上的小部件。

django - how can I access the form field from inside a custom widget

这是关于访问表单实例的自定义小部件的另一个问题。

Country/State/City dropdown menus inside the Django admin inline

答案 1 :(得分:1)

除了选择的答案: 要使用AdvancedModelChoiceField,并且仍然通过常规小部件呈现表单,我将继承了django小部件并覆盖了一些方法。 第一种方法是optgroups。替换

for index, (option_value, option_label) in enumerate(chain(self.choices)):

for index, (option_value, option_label, obj) in enumerate(chain(self.choices)):

然后,我们需要将该obj传递给选项。

def create_option(self, name, value, label, selected, index, subindex=None, attrs=None, obj=None):
    option = super(RadioSelect, self).create_option(name, value, label, selected, index, subindex, attrs)
    option['obj'] = obj
    return option

在小部件模板中访问obj,如下所示:

{{ widget.obj.object_attr }}

最后,我们可以在表单中使用我们的自定义窗口小部件和字段:

class MyForm(forms.ModelForm):
myfield = AdvancedModelChoiceField(
    widget=MyWidget,
    queryset=MyModel.objects.all(),
    empty_label=None
)

答案 2 :(得分:0)

覆盖您将使用此小部件的模型字段,并将小部件设置为默认小部件。设置默认小部件时,实例化小部件并传递您需要的任何内容。

例如,我重写ForeignKey类以在select输入后添加链接。

小部件:

class SelectAdd(widgets.Select):
    def __init__(self, related_name, related_create_url, attrs=None):
        self.related_name = related_name
        self.related_create_url = related_create_url
        super().__init__(attrs=attrs)

    def render(self, name, value, attrs=None, **kwargs):
        rendered = super(SelectAdd, self).render(name, value, attrs, **kwargs)
        return rendered + mark_safe(u'''
           <span>Add new {} : {}</span>
           '''.format(self.related_name, self.related_create_url))

模型字段:

class ForeignKeyAdd(ForeignKey):
    def formfield(self, **kwargs):
        db = kwargs.pop('using', None)
        if isinstance(self.remote_field.model, six.string_types):
            raise ValueError("Cannot create form field for %r yet, because "
                             "its related model %r has not been loaded yet" %
                             (self.name, self.remote_field.model))
        defaults = {
            'form_class': forms.ModelChoiceField,
            'queryset': self.remote_field.model._default_manager.using(db),
            'to_field_name': self.remote_field.field_name,
            'widget': SelectAdd(
                related_name=self.name,
                related_create_url=get_crud_url(self.related_model, 'create')
            ),
        }
        defaults.update(kwargs)
        return super(ForeignKey, self).formfield(**defaults)