【问题标题】:django: exclude certain form elements based on a conditiondjango:根据条件排除某些表单元素
【发布时间】:2011-08-30 07:10:38
【问题描述】:

我有一些表单字段,我想根据是否满足某个条件来包含/排除这些字段。我知道如何包含和排除表单元素,但是当我希望它根据函数的结果显示元素时,我很难做到。

这是我的表格:

class ProfileForm(ModelForm):
    # this_team = get Team instance from team.id passed in
    # how?

    def draft_unlocked(self):
        teams = Team.objects.order_by('total_points')
        count = 0
        for team in teams:
            if team.pk == this_team.pk:
                break
            count += 1

        now = datetime.datetime.now().weekday()
        if now >= count:
            # show driver_one, driver_two, driver_three
        else:
            # do not show driver_one, driver_two, driver_three

class Meta:
    model = Team

我想要完成的是,根据总积分的排名,车队在指定日期之前不能更换车手。例如,积分榜上的最后一支球队可以在星期一添加/删除一名车手,倒数第二名的球队可以在星期二添加/删除,依此类推......

所以第一个问题——如何从传入的 id 中获取表单本身内部的 Team 实例。以及如何根据 draft_unlocked() 的结果包含/排除。

或者也许有更好的方法来完成这一切?

非常感谢大家。

【问题讨论】:

    标签: python django forms


    【解决方案1】:

    这实际上相当简单(条件字段设置) - 这是一个简单的示例:

    from django.forms import Modelform
    from django.forms.widgets import HiddenInput
    
    class SomeForm(ModelForm):
    
        def __init__(self, *args, **kwargs):
            # call constructor to set up the fields. If you don't do this 
            # first you can't modify fields.
            super(SomeForm, self).__init__(*args, **kwargs)
    
            try:
                # make somefunc return something True
                # if you can change the driver.
                # might make sense in a model?
                canchangedriver = self.instance.somefunc()                          
            except AttributeError:
                # unbound form, what do you want to do here?
                canchangedriver = True # for example?
    
            # if the driver can't be changed, use a input=hidden
            # input field.
            if not canchangedriver:
                self.fields["Drivers"].widget = HiddenInput()
    
        class Meta:
            model = SomeModel
    

    所以,这里的关键点:

    • self.instance 表示绑定的对象,如果表单已绑定。我相信它是作为命名参数传入的,因此在 kwargs 中,父构造函数使用它来创建 self.instance
    • 您可以在调用父构造函数后修改字段属性。
    • 小部件是表单的显示方式。 HiddenInput 基本上是指<input type="hidden" .../>

    有一个限制;如果我修改提交的 POST/GET 数据,我可以篡改输入以更改值。如果您不希望这种情况发生,需要考虑的是覆盖表单的验证 (clean()) 方法。请记住,Django 中的所有内容都只是对象,这意味着您实际上可以修改类对象并向它们随机添加数据(尽管它不会被持久化)。因此,在您的 __init__ 中,您可以:

    self.instance.olddrivers = instance.drivers.all()
    

    然后在您的干净方法中为所述表单:

    def clean(self):
        # validate parent. Do this first because this method
        # will transform field values into model field values.
        # i.e. instance will reflect the form changes.
        super(SomeForm, self).clean()
    
        # can we modify drivers?
        canchangedriver = self.instance.somefunc() 
    
        # either we can change the driver, or if not, we require 
        # that the two lists are, when sorted, equal (to allow for 
        # potential non equal ordering of identical elements).
    
        # Wrapped code here for niceness
        if (canchangedriver or 
                       (sorted(self.instance.drivers.all()) == 
                        sorted(self.instance.olddrivers))):  
            return True
        else:
            raise ValidationError() # customise this to your liking.
    

    【讨论】:

      【解决方案2】:

      您可以通过添加自己的 init 来做您需要的事情,您可以在实例化表单类时传入 id:

      class ProfileForm(ModelForm):
          def __init__(self, team_id, *args, **kwargs):
              super(ProfileForm, self).__init__(*args, **kwargs)
      
              this_team = Team.objects.get(pk=team_id)
      
              teams = Team.objects.order_by('total_points')
              count = 0
              for team in teams:
                  if team.pk == this_team.pk:
                      break
                  count += 1
      
              now = datetime.datetime.now().weekday()
              if now >= count:
                  # show driver_one, driver_two, driver_three
              else:
                  # do not show driver_one, driver_two, driver_three
      
      class Meta:
          model = Team
      
      #views.py
      def my_view(request, team_id):
          profile_form = ProfileForm(team_id, request.POST or None)
          #more code here
      

      希望对你有所帮助。

      【讨论】:

        猜你喜欢
        • 2016-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-11
        • 1970-01-01
        • 2022-06-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多