Django-将两个模型之间的关系呈现为单选按钮
我有以下型号:Django-将两个模型之间的关系呈现为单选按钮,django,django-models,django-forms,Django,Django Models,Django Forms,我有以下型号: class Profile(models.Model): verified = models.BooleanField(default=False) primary_phone = models.OneToOneField('Phone', related_name='is_primary', null=True, blank=True) class Phone(models.Model): profile = models.ForeignKey(Pro
class Profile(models.Model):
verified = models.BooleanField(default=False)
primary_phone = models.OneToOneField('Phone', related_name='is_primary', null=True, blank=True)
class Phone(models.Model):
profile = models.ForeignKey(Profile)
type = models.CharField(choices=PHONE_TYPES, max_length=16)
number = models.CharField(max_length=32)
@property
def is_primary(self):
return profile.primary_phone == self
及下列表格:
class PhoneForm(ModelForm):
class Meta:
from accounts.models import Phone
model = Phone
fields = ('type', 'number', )
正在modelformset\u工厂中使用的
我以如下方式呈现表单集:
<div class="span-13 last">
{{ formset.management_form }}
{% for form in Phones %}
<div class="span-2">{{ form.type|add_class:'dropdown' }}</div>
<div class="span-11 last">{{ form.number|add_class:'phone-number' }}</div>
<div class="clearfix"></div>
{% endfor %}
</div>
但是,它为Phone
的每个实例显示两个单选按钮,而我需要它为每个实例只显示一个单选按钮。我要玩一会儿,看看是否能正确显示出来。而不是:
class Profile(models.Model):
verified = models.BooleanField(default=False)
primary_phone = models.OneToOneField('Phone', related_name='is_primary', null=True, blank=True)
class Phone(models.Model):
profile = models.ForeignKey(Profile)
type = models.CharField(max_length=16)
number = models.CharField(max_length=32)
你应该:
class Profile(models.Model):
verified = models.BooleanField(default=False)
def primary_phone(self):
return self.phone_set.get(primary=True)
class Phone(models.Model):
profile = models.ForeignKey(Profile)
type = models.CharField(max_length=16)
number = models.CharField(max_length=32)
primary = models.BooleanField(default=False)
def save(self, force_insert=False, force_update=False, using=None):
if self.primary:
# clear the primary attribute of other phones of the related profile
self.profile.phone_set.update(primary=False)
self.save(force_insert, force_update, using)
那会让你的生活更轻松
如果您无法进行此更改:电话表单集实际上是许多电话表单的包装器。但您要查找的字段允许编辑Profile.primary\u phone
因此,一种方法是手动操作:
{% for form in Phones %}
<input type="radio" name="primary_phone" checked="{% if form.instance == profile.primary_phone %}checked{% endif %}" value="{{ form.instance.pk }}" />
<!-- snip ... ->
我们在这里使用一个布尔字段,因为对于每个电话表单,主字段是要设置还是不设置。但是,您仍然必须自己渲染它:
{% for form in Phones %}
<input type="checkbox" name="{{ form.prefix }}-primary" checked="{% if form.instance == profile.primary_phone %}checked{% endif %}" value="true" />
<!-- snip ... ->
当然,您应该更新上述示例中的选择器,以确保只影响“主电话”复选框
最后,要连接复选框,类似这样的操作可能会起作用:
class PhoneForm(forms.ModelForm):
primary = forms.BooleanField(required=False)
def __init__(self, *args, **kwargs):
super(PhoneForm, self).__init__(*args, **kwargs)
if self.instance.is_primary:
self.data['primary'] = True
def save(self, *args, **kwargs):
super(PhoneForm, self).save(*args, **kwargs)
if self.cleaned_data['primary']:
self.profile.primary_phone = self
self.profile.save()
这确实有效,对于空的Phone
表单value
是None
,因此我可以在发出POST
请求时处理它们,并检查它们是否有值。我希望少一些自定义编码/多一些django风格的方式。我喜欢你的第一种方式!我可以更改模型,但是现在当我尝试渲染每个手机
实例的单选按钮时,它会为每个实例显示两个单选按钮(true/false)。我会在一分钟内编辑我的帖子,告诉你我的意思。
{% for form in Phones %}
<input type="checkbox" name="{{ form.prefix }}-primary" checked="{% if form.instance == profile.primary_phone %}checked{% endif %}" value="true" />
<!-- snip ... ->
$('input[type=checkbox]').change(function() {
$('input[type=checkbox][checked=checked]').attr('checked', '');
$(this).attr('checked', 'checked');
});
class PhoneForm(forms.ModelForm):
primary = forms.BooleanField(required=False)
def __init__(self, *args, **kwargs):
super(PhoneForm, self).__init__(*args, **kwargs)
if self.instance.is_primary:
self.data['primary'] = True
def save(self, *args, **kwargs):
super(PhoneForm, self).save(*args, **kwargs)
if self.cleaned_data['primary']:
self.profile.primary_phone = self
self.profile.save()