【问题标题】:Change the order of a model form when optionally adding an extra field?可选添加额外字段时更改模型表单的顺序?
【发布时间】:2014-10-01 14:17:52
【问题描述】:

我有这个模型:

class Server(models.Model):
  user = models.ForeignKey('auth.User',related_name="servers")
  is_shared = models.BooleanField(default=True, editable=False)
  name = models.CharField(max_length=255, default='testserver')
  hostname = models.CharField(max_length=255, default='localhost')
  username = models.CharField(max_length=255, default='user')
  password = models.CharField(max_length=255, default='pass')
  path = models.CharField(max_length=255, default='/')
  mkdir = models.BooleanField(default=False)
  port = models.IntegerField(max_length=4, default=21)
  quirky = models.BooleanField(default=False)
  class Meta:
    unique_together = ('user', 'name',)
  def __unicode__(self):
    return self.name
  class Meta:
    verbose_name_plural = "Server"

我正在创建一个模型表单:

class ServerForm(ModelForm):
  delete = forms.BooleanField(required=False)

  def __init__(self, *args, **kwargs):
    super(ServerForm, self).__init__(*args,**kwargs)
    if (self.instance.pk is None):
        self.fields['name'] = forms.CharField(max_length=255, required=True)
        del self.fields['delete']
  class Meta:
    model = Server
    exclude = ["user","name"]

关键是用户可能不会更改现有服务器对象的名称字段,但如果表单没有实例,我希望用户指定名称。换句话说:用户应该提供一个名称,但以后不要更改它。

当我使用此代码时,名称最终位于底部,但它应该位于顶部。在较早的 django 版本中,插入可以解决问题,但是自从进入 django 1.7 以来,这不再起作用了。

然后我在这里读到: How can I order fields in Django ModelForm?

... 使用元类中的字段值。但现在我遇到的问题是字段列表有时应包含“名称”,而有时则不包含。取决于是否有实例。但是从 Meta 类我不能使用 self.instance 来检查。再次列出所有字段只是为了改变那里的顺序似乎有点烦人。

如何更改模型表单字段的顺序?

编辑:我很想继续在模板中循环。此外,在管理员以及任何模板中都有正确的顺序会很好。不过,模板更重要。

【问题讨论】:

  • 您是在谈论在 Django admin 中订购它们吗?还是在公共方面的表单输出中?
  • 我说的是公共方面。不过,将它放在管理员中也很好。我猜你的解决方案是不在模板中循环?我希望避免这种情况..
  • 请耐心等待几分钟,我正在为您收集样本。
  • 谢谢。我会留下来的。目前我正在尝试实施您的建议,然后我将尝试使用更新表单和一个额外的表单添加一个表单集来添加新内容。
  • Grr。好吧,不幸的是,我的例子碰了壁。可以创建一个返回元类的函数,例如 ModelForm 上的 Media,您可以在其中访问 self,但不幸的是,我似乎无法仅对 ModelForm 的 Meta 类执行相同操作。

标签: python django forms django-forms django-1.7


【解决方案1】:

我可能会利用继承并做这样的事情:

class ServerForm(ModelForm):

  def __init__(self, *args, **kwargs):
    super(ServerForm, self).__init__(*args,**kwargs)
    self.fields['name'] = forms.CharField(max_length=255, required=True)

    class Meta:
      model = Server
      exclude = ["user","name"]


class ServerUpdateForm(ServerForm):
  delete = forms.BooleanField(required=False)

  def __init__(self, *args, **kwargs):
    super(ServerForm, self).__init__(*args,**kwargs)

  class Meta:
    model = Server
    exclude = ["user","name"]

【讨论】:

  • 我没想到。但是我也可以将这个新表单添加到表单集中吗?我认为它必须一遍又一遍地使用相同的形式。每次我尝试在一个表单集中使用不同的表单时都失败了。
  • 您应该可以执行 ServerFormSet = inlineformset_factory(ServerForm, ServerUpdateForm),但我想这取决于您显示单独表单的特定条件。
  • “inlineformset_factory”的文档似乎有点薄,但我会试一试。
  • 我认为“inlineformset_factory”是行不通的。据我了解,它需要两个通过外键连接的相关模型。还有什么可以在一个表单集中组合不同的表单吗?
【解决方案2】:

老问题,但我很容易通过 jQuery 做到这一点。这比弄乱Meta 或为每个表单输入字段(尤其是那些不能很好继承的字段)要快。我将它用于我的管理页面:

$("selector_for_field").insertBefore($(".form-row:first"));

根据表单布局的需要调整选择器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多