我想创建一个表单,该表单显示2个不同的文本框,其中包含模型价格字段的最小值和最大值,即DecimalField。但是我不确定从哪里开始。我知道我可以计算最小值和最大值,但是我不确定如何将其添加到占位符和/或值文本中。因此,就目前而言,我仅使用视图来推送值,但它们不会在表单中提交。到目前为止,这是我的代码:
forms.py
class ProductSearchForm(forms.ModelForm):
price_min = forms.DecimalField()
price_max = forms.DecimalField()
def __init__(self, *args, **kwargs):
super(ProductSearchForm, self).__init__(*args, **kwargs)
self.fields['length_range'].empty_label = "any size"
self.fields['hull_type'].empty_label = "any type"
self.fields['power'].empty_label = "any type"
self.fields['speed'].empty_label = "any speed"
self.fields['hull_only_available'].empty_label = None
self.fields['price_min'].widget.attrs['min'] = kwargs['price']['price__min']
self.fields['price_max'].widget.attrs['max'] = kwargs['price']['price__max']
class Meta:
model = Product
fields = ('length_range', 'hull_type', 'price', 'power', 'speed', 'hull_only_available')
views.py
class IndexView(FormView):
template_name = 'index.html'
form_class = ProductSearchForm
success_url = "search/"
def get_price(self):
price = getattr(self, "_price", None)
if price is None:
price = Product.objects.all().aggregate(Min('price'), Max('price'))
setattr(self, "_price", price)
return price
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context['length_ranges'] = LengthRange.objects.all().order_by('pk')
context['hull_types'] = Hull.objects.all().order_by('pk')
context['power_configs'] = PowerConfiguration.objects.all().order_by('pk')
context['speed_ranges'] = SpeedRange.objects.all().order_by('pk')
return context
def get_form_kwargs(self):
form_kwargs = super(IndexView, self).get_form_kwargs()
form_kwargs['price'] = self.get_price()
return form_kwargs
index.html
<form class="nl-form" action="{% url 'boatsales:search' %}" method="get">
A boat with a length of
{{ form.length_range }}
, with hull type of
{{ form.hull_type }}
with
{{ form.power }}
power
configuration and a top speed between
{{ form.speed }}.
My budget is from $<input type="text" value="{{ price.price__min|intcomma }}"
placeholder="{{ price.price__min|intcomma }}"
data-subline="Our current lowest price is: <em>{{ price__min|intcomma }}</em>"/>
to
$<input
type="text" value="{{ price.price__max|intcomma }}"
placeholder="{{ price.price__min|intcomma }}"
data-subline="Our current highest price is: <em>{{ price.price__min|intcomma }}</em>"/>.
Hull only
availability <select>
<option value="False" selected>is not</option>
<option value="True">is</option>
</select> a concern.
<div class="container">
<button type="submit"
class="btn-a btn-a_size_large btn-a_color_theme">
Show me the results!
</button>
</div>
</form>
编辑
现在,我收到一个TypeError:__init__() got an unexpected keyword argument 'price'
似乎来自views.py中的这一行
context = super(IndexView, self).get_context_data(**kwargs)
答案 0 :(得分:0)
抱歉,请忽略我之前的回答,我完全误解了您的问题。
我认为这里的问题是您正在创建一个仅包含Product
中包含的字段的表单。
但是,您需要一个包含更多字段的表单。没有什么限制您只能使用模型中的字段。
因此,想法是忽略price
(这是一个特定的价格),而是添加price_min
和price_max
:
class ProductSearchForm(forms.ModelForm):
price_min = form.DecimalField()
price_max = form.DecimalField()
def __init__(self, *args, **kwargs):
# Pop the price argument, as the parent form doesn't know about it!
price = kwargs.pop("price")
super(ProductSearchForm, self).__init__(*args, **kwargs)
# ... existing code...
self.fields['price_min'].widget.attrs['min'] = price['price__min']
self.fields['price_min'].widget.attrs['max'] = price['price__max']
self.fields['price_max'].widget.attrs['min'] = price['price__min']
self.fields['price_max'].widget.attrs['max'] = price['price__max']
您可以将模板中的这些字段用作其他任何常规字段。
然后,您可以尝试通过get_form_kwargs
传递当前价格值:
class IndexView(FormView):
# ... existing code...
def get_form_kwargs(self):
form_kwargs = super(IndexView, self).get_form_kwargs()
form_kwargs['price'] = Product.objects.all().aggregate(Min('price'), Max('price'))
return form_kwargs
其他建议:
如果您要避免对Product
进行两次查询以获取最小值/最大值,则可以创建一种缓存结果的方法,例如:
(在视图中)
def get_price(self):
price = getattr(self, "_price", None)
if price is None:
price = Product.objects.all().aggregate(Min('price'), Max('price'))
setattr(self, "_price", price)
return price
然后您可以调用self.get_price()
来填充表单kwargs和模板上下文。