首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django -将两个模型之间的关系呈现为单选按钮。

Django -将两个模型之间的关系呈现为单选按钮。
EN

Stack Overflow用户
提问于 2012-03-17 10:58:07
回答 1查看 655关注 0票数 0

我有以下几种型号:

代码语言:javascript
复制
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

和下列表格:

代码语言:javascript
复制
class PhoneForm(ModelForm):
    class Meta:
        from accounts.models import Phone
        model = Phone
        fields = ('type', 'number', )

它正在modelformset_factory中使用。

我是这样渲染表单集的:

代码语言:javascript
复制
<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模型的Phone属性。通过Phone模型本身或通过Profile.primary_phone确定这种关系有两种方法。但是,我将Phone模型呈现为一个表单集,因此对它的实例进行循环,所以我尝试在PhoneForm字段中包含'is_primary',但是由于它是一个属性,所以它无法工作。

知道怎么做吗?

更新#1:

我使用了jpic方法并尝试将primary呈现为单选按钮:

代码语言:javascript
复制
class PhoneForm(ModelForm):
    primary = forms.BooleanField(widget=forms.RadioSelect( choices=((0, 'False'), (1, 'True')) ))

    class Meta:
        from accounts.models import Phone
        model = Phone
        fields = ('primary', 'type', 'number', )

但是,它为Phone的每个实例显示了两个单选按钮,而我需要它只显示每个实例一个单选按钮。我要用它玩一会儿,看看我能不能让它正确地显示出来。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-03-17 11:13:33

而不是:

代码语言:javascript
复制
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)

你应该:

代码语言:javascript
复制
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_phone。

因此,这样做的一种方法是手动地这样做:

代码语言:javascript
复制
{% for form in Phones %}
    <input type="radio" name="primary_phone" checked="{% if form.instance == profile.primary_phone %}checked{% endif %}" value="{{ form.instance.pk }}" />
    <!-- snip ... ->

但是问题是,由于这个值是{{ form.instance.pk }},所以这个收音机不会有一个空电话表单的值。

另一种方法是向PhoneForm添加一个复选框:

代码语言:javascript
复制
from django import forms

from accounts.models import Phone

class PhoneForm(forms.ModelForm):
    primary = forms.BooleanField(required=False, default=False)

    class Meta:
        model = Phone
        fields = ('type', 'number', )

我们在这里使用BooleanField,因为对于每个电话表单,主都要设置或不设置。不过,你还是得自己动手:

代码语言:javascript
复制
{% for form in Phones %}
    <input type="checkbox" name="{{ form.prefix }}-primary" checked="{% if form.instance == profile.primary_phone %}checked{% endif %}" value="true" />
    <!-- snip ... ->

但是,您需要javascript来确保在同一时间只检查一台收音机,例如使用jQuery:

代码语言:javascript
复制
$('input[type=checkbox]').change(function() {
    $('input[type=checkbox][checked=checked]').attr('checked', '');
    $(this).attr('checked', 'checked');
});

当然,您应该更新上面示例中的选择器,以确保只影响“主电话”复选框。

最后,要连接复选框,这样的操作可能会奏效:

代码语言:javascript
复制
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()
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9749420

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档