0

在发布自己的问题之前,我检查了很多相关问题,但我仍然无法弄清楚。使用 Django 2.2.x。

我希望owner我的 html 表单字段最初只显示 1 个用户名,并且该用户名必须是当前event实例所有者。

作为 a ModelChoiceField,html 表单上的字段呈现为下拉列表。这个下拉列表暂时包含所有应用程序用户,因为ModelChoiceFieldqueryset=User.objects.all()

我试图覆盖get_initial()我的方法,UpdateView但是,这对ModelChoiceField. 我可以设置所有 forms.CharField() 初始值。

我也试图在没有运气的情况下覆盖__init__我的方法。class EventForm(forms.ModelForm)

forms.py

class EventForm(forms.ModelForm):

    class Meta:
        model = Event
        fields = ["customer", "owner", ...]

    # the helper block comes from crispy_forms extension.
    # It rules the form layout, allowing to specify css classes, fields order
    # and even adding custom buttons
    helper = FormHelper()
    helper.layout = Layout(
        Field('customer'),
        Field('owner'),
        ...    
        Submit('submit', 'Update')
    )

    customer = forms.CharField(disabled=True)
    owner = forms.ModelChoiceField(queryset=User.objects.all())
    ...

views.py

class EventUpdateView(LoginRequiredMixin, UpdateView):
    """ this view renders the update form that allows service desk operators to update event status,
    ownership and event notes
    """
    model = Event
    form_class = EventForm
    template_name = "metamonitor/event_update_form.html"

    def get_initial(self):
        """ returns the initial data to populate form field on this view.
        We override this method to customize the `owner` initial value to the
        default event owner.
        """
        initial = super().get_initial()
        # the event instance being updated
        event = self.get_object()
        # this expression returns a queryset containing only 1 item,
        # like <QuerySet [<User: operator2>]>
        initial['owner'] = User.objects.filter(pk=event.owner.pk)

        return initial

    # without this, after a successfull event update we would get an error
    # because django needs a valid url to redirect to.
    def get_success_url(self):
        # app_name:url_name, as defined in the corresponding path() `name` argument in urls.py
        return reverse("metamonitor:event_update", kwargs={"pk": self.object.pk})

如何正确设置初始值?

4

1 回答 1

1

这是解决您的问题的方法。它需要两个步骤:

  1. 覆盖视图的 get_form_kwargs 方法,因此它检索“所有者”对象并将其发送到表单,存储在 kwargs 参数中

  2. 覆盖表单的init,然后将所有者对象(取自 kwargs)分配给要更改的字段的 .queryset:

在您的视图中覆盖 get_form_kwargs :

def get_form_kwargs(self):
    kwargs = super().get_form_kwargs()
    event = self.object     # no need to call get_object() as you did in your post
    owner = User.objects.filter(pk=event.owner.pk)
    kwargs.update({'owner': owner})
    return kwargs

在 forms.py 中覆盖Form 类的 init

def __init__(self, *args, **kwargs):
    owner = kwargs.pop('owner')   # get the owner object from kwargs
    super().__init__(*args, **kwargs)
    # assign owner to the field; note the use of .queryset on the field
    self.fields['owner'].queryset = owner 

另一种与上述不同的方法是简单地修改视图的get_form方法:

def get_form(self, form_class=None):
    form = super().get_form(form_class)
    event = self.object
    owner = User.objects.filter(pk=event.owner.pk)
    form.fields['owner'].queryset = owner

    return form

这个解决方案比第一个解决方案实施起来要快得多,这是真的;我只在最后提到它,因为根据我的经验,当期望的目标是改变 Form 的显示方式时,人们似乎更喜欢修改 Form 类本身。使用最适合您需求的方法。

于 2020-11-10T18:11:27.830 回答