Django RadioSelect小部件,添加其他信息
我有这个简化的模型和形式:Django RadioSelect小部件,添加其他信息,django,django-forms,django-crispy-forms,Django,Django Forms,Django Crispy Forms,我有这个简化的模型和形式: class Books(models.Model): name = models.CharField(max_length=500) price = models.DecimalField(max_digits=6, decimal_places=2) default = models.BooleanField(default=False) def __str__(self): return self.name
class Books(models.Model):
name = models.CharField(max_length=500)
price = models.DecimalField(max_digits=6, decimal_places=2)
default = models.BooleanField(default=False)
def __str__(self):
return self.name
class BookForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['Field'] = forms.ModelChoiceField(queryset=None, empty_label=None, widget=forms.RadioSelect)
self.fields['Field'].queryset = Books.objects.all()
self.fields['Field'].initial = Books.objects.filter(default=True).first()
这将生成一个RadioSelect表单,如下所示:
(x) Book1
( ) Book2
( ) Book3
class BookForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['Field'] = forms.ModelChoiceField(queryset=None, empty_label=None, widget=forms.RadioSelect)
self.fields['Field'].queryset = Books.objects.all()
self.fields['Field'].initial = Books.objects.filter(default=True).first()
# customize how your option is rendered in the template
self.fields["Field"].label_from_instance = lambda item: f"{item} ({item.price} €)"
<form action="{% url 'books' %}" method="post">
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
<ul>
{% for choice in form.Field %}
<li>{{ choice.choice_label|safe }}</li>
{% endfor %}
</ul>
<input class="btn btn-dark" type="submit" value="Submit">
</form>
我的问题是,我如何在RadioSelect表单中添加价格,因为它是可见的。
它应该出现在书名之后,理想情况下甚至是以不同的字体出现,这是我在引导类上设置的(例如“text primary”)(这不是强制性的)
我知道我可以在模型中返回名称和价格,如
class Books(models.Model):
name = models.CharField(max_length=500)
price = models.DecimalField(max_digits=6, decimal_places=2)
default = models.BooleanField(default=False)
def __str__(self):
return '%s (%s €)' % (self.value, str(self.price))
但由于其他原因,我不能这样做。我只需要返回名字。还有其他方法吗
我甚至阅读了django crispy表单,但找不到解决方案。您可以使用
.label\u from\u instance
从:
将调用模型的\uuu str\uu()
方法来生成对象的字符串表示形式,以便在字段的选择中使用。若要提供自定义表示,请将modelcoocefield
子类化,并覆盖label\u from\u instance
您可以定义一个函数,为您提供所需的表示形式,然后在字段上设置.label\u from\u instance
您的书单
如下所示:
(x) Book1
( ) Book2
( ) Book3
class BookForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['Field'] = forms.ModelChoiceField(queryset=None, empty_label=None, widget=forms.RadioSelect)
self.fields['Field'].queryset = Books.objects.all()
self.fields['Field'].initial = Books.objects.filter(default=True).first()
# customize how your option is rendered in the template
self.fields["Field"].label_from_instance = lambda item: f"{item} ({item.price} €)"
<form action="{% url 'books' %}" method="post">
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
<ul>
{% for choice in form.Field %}
<li>{{ choice.choice_label|safe }}</li>
{% endfor %}
</ul>
<input class="btn btn-dark" type="submit" value="Submit">
</form>
要在标签上应用CSS,请添加HTML。除了使用style='…'
之外,还可以使用类,使其与引导一起工作
self.fields["Field"].label_from_instance = lambda item: f"{item} <span style='color:red;'>({item.price} €)</span>"
过滤器是必需的,这样你的HTML就不会被转义。如果你不能连接标签,我相信信息不在你的模型中或者更接近的东西中。。。所以我相信挑战仍在形式上。。。可以使用ajax吗?从端点(URL)加载额外数据并将其连接到客户端的javascript?谢谢你的想法,但我对ajax/javascript不太熟悉。也许我必须把标签连在一起,在以后的某个时候去掉价格,这是一个有点黑客的Solution imo。额外的信息在哪里?在您的数据库中,或者您必须从其他站点(或外部服务)获取它?非常感谢!您能否详细介绍一下这个lambda函数以及项来自何处?lambda函数在呈现模板时获取
Book
实例,以获取标签。你可以使用一个普通的函数和一个参数来代替lambda,它只需要是可调用的,然后返回你想要的标签在呈现的模板中的样子。您推荐未来的fstring,还是有其他方法为python 3.5编写它?我添加了一种不使用f-string的方法,您也可以使用.format()
,但我发现f-string比其他方法好得多。这对python 3.5和之前的版本也适用:lambda obj:“%s+(++%s€”)”%(obj,obj.price)