我在Django中使用基于模型的表单。所以它看起来像这样:
240 class EventDetailForm(NgFormValidationMixin, NgModelForm):
241 def __init__(self, *args, **kwargs):tha
242 super(EventDetailForm, self).__init__(*args, **kwargs)
243 self.fields['gallery'].queryset = Gallery.objects.none()
244
245 class Meta:
246 model = Event
247 fields = ('title', 'description', 'end_date', 'start_date', 'gallery', 'cover_photo')
248 widgets = {
249 'title': forms.TextInput(attrs={
250 'editable-detail': '',
251 }),
252 'description': forms.TextInput(attrs={
253 'class': 'panel-body',
254 'id': 'event-description-editable',
255 'editable-detail': '',
256 }),
257 'cover_photo': SelectWithDefaultOptions(attrs={
258 'class': 'chosen-select-no-single',
259 'id': 'select-cover-photo',
260 'data-placeholder': 'Select Cover Photo',
261 'style': 'width: 200px;',
262 'tabindex': '-1',
263 }),
264 'start_date': DateTimeWidget(attrs = {
265 'class': 'datetimepicker col-xs-6',
266 'id': 'event-start-date-editable',
267 'editable-detail': '',
268 }),
269 'end_date': DateTimeWidget(attrs = {
270 'class': 'datetimepicker col-xs-6',
271 'id': 'event-end-date-editable',
272 'editable-detail': '',
273 }),
274 'gallery': SelectWithDefaultOptions(attrs={
275 'class': 'chosen-select-no-single',
276 'id': 'select-galley',
277 'data-placeholder': 'Select Gallery',
278 'style': 'width: 200px;',
279 'gallery-select': '',
280 'tabindex': '-1',
281 'organisator-profile-specific': '',
282 }
283 }
所以会发生的是我的gallery和cover_photo选择小部件被两种类型的所有现有对象填充(因为它们实际上是其他模型的外键)。 我想要阻止它,正如你在第243行看到的那样,我试图删除当前的查询集(尝试使用相同的清理选项),这非常有效。问题是,你看到我使用我的自定义选择小部件,我在其中设置了一些默认选项。它看起来像这样:
62 class SelectWithDefaultOptions(forms.Select):
63 def __init__(self, attrs=None, choices=()):
64 super(SelectWithDefaultOptions, self).__init__(attrs, choices)
65
66 choices = ('', 'empty') + choices
67 choices = ('None', 'no selection') + choices
问题在于,通过我上面提到的方法,我删除了这些值。 所以我告诉自己"好吧,我会得到所需的值,擦除所有值并放回首选的"。尝试了但事实证明,实际上Django放入的对象正在删除已经设置的对象。 (在init方法通过后添加默认值) 所以我想"好吧,如果我在小部件的初始化中设置choices =()(第274行),Django不应该在其上设置任何其他值,因为这将违反我的选择"所以我试了一下,但事实证明,Django实际上并不关心我想要的选择和行为。 还尝试设置字段' initial'财产,仍然没有结果。
那么,如何防止DJango默认将引用的对象放入我的选择列表中呢?
感谢。
答案 0 :(得分:0)
widget
中定义的Meta
导致此问题。如果您刚将其移至__init__
,则可以正常使用。首先更新您的小部件,行choices
中的关键字def __init__(self, attrs=None, choices=())
表示默认情况下的选项为空,但任何实例都可以覆盖它,并传入一些值。所以你需要明确地将它设置为空元组:
class SelectWithDefaultOptions(forms.Select):
def __init__(self, attrs=None, choices=()):
super(SelectWithDefaultOptions, self).__init__(attrs, choices)
choices = () # explicitly setting choices to empty here
choices += (('', 'empty'),)
choices += (('None', 'no selection'),)
self.choices = choices
现在更新您的表单,将小部件分配到gallery
中的__init__
字段,而不是Meta
类:
class EventDetailForm(NgFormValidationMixin, NgModelForm):
def __init__(self, *args, **kwargs):
super(EventDetailForm, self).__init__(*args, **kwargs)
self.fields['gallery'].widget = SelectWithDefaultOptions(attrs={
'class': 'chosen-select-no-single',
'id': 'select-galley',
'data-placeholder': 'Select Gallery',
'style': 'width: 200px;',
'gallery-select': '',
'tabindex': '-1',
'organisator-profile-specific': '',
}
class Meta:
model = Event
fields = ('title', 'description', 'end_date', 'start_date', 'gallery', 'cover_photo')
或者您根本不需要任何自定义小部件。只需在表单__init__
方法中设置选项,并将SelectWithDefaultOptions
小部件名称替换为forms.Select
中的Meta
(这更简洁,更简洁):
class EventDetailForm(NgFormValidationMixin, NgModelForm):
def __init__(self, *args, **kwargs):
super(EventDetailForm, self).__init__(*args, **kwargs)
self.fields['gallery'].widget.choices = (('', 'Empty',),)
class Meta:
model = Event
fields = ('title', 'description', 'end_date', 'start_date', 'gallery', 'cover_photo')
widgets = {
'gallery': forms.Select(attrs={
'class': 'chosen-select-no-single',
'id': 'select-galley',
'data-placeholder': 'Select Gallery',
'style': 'width: 200px;',
'gallery-select': '',
'tabindex': '-1',
'organisator-profile-specific': '',
}),
}
答案 1 :(得分:0)
这是我修复它的方法,在@AamirAdnan:
的帮助下 65 class SelectWithDefaultOptions(forms.Select):
66 def render(self, name, value, attrs=None, choices=()):
67 choices = ()
68 choices += (('empty', ''),)
69 choices += (('no selection', 'None'),)
70 self.choices = choices
71
72 if value is None:
73 value = ''
74
75 final_attrs = self.build_attrs(attrs, name=name)
76 output = [format_html('<select{0}>', flatatt(final_attrs))]
77 options = self.render_options((), [value])
78
79 if options:
80 output.append(options)
81 output.append('</select>')
82
83 return mark_safe('\n'.join(output))
刚刚改进了小部件渲染功能。
这不是所要求的,但它确实有效。会发生什么:
1. Django将选择值设置为引用的对象
2.在呈现窗口小部件之前,它们将更改为正确的选择