【问题标题】:Django - Get instance pk inside form widget classDjango - 在表单小部件类中获取实例 pk
【发布时间】:2011-03-30 15:29:06
【问题描述】:

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

谢谢

【问题讨论】:

    标签: django-models django-forms


    【解决方案1】:

    您可以覆盖小部件的__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

    【讨论】:

      【解决方案2】:

      除了选择的答案: 为了使用 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
      )
      

      【讨论】:

        【解决方案3】:

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

        例如,我重写 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)
        

        【讨论】:

          猜你喜欢
          • 2010-12-21
          • 1970-01-01
          • 2018-07-03
          • 2015-04-11
          • 1970-01-01
          • 2020-07-14
          • 1970-01-01
          • 2014-04-23
          • 2023-03-02
          相关资源
          最近更新 更多