Django ManyToMany字段使用通过关系值

时间:2013-08-25 16:28:54

标签: django

我有一个包含多对多字段的模型,它通过具有布尔值的表链接的字段。

我在不同的场景中得到了这个,让我们以用户为主要模型,感兴趣为多对多字段和user_interest模型作为直通模型,在user_interest中我有一个布尔字段,我希望用户在选择每个时指定他的多重价值,

目前我正试图找到一个合适的表单界面来满足我的需求,目前正在使用只显示感兴趣的选择的MultipleSelect小部件,是否有任何字段控制的例子可以让我选择兴趣并指定布尔字段的值?如果没有,在我的情况下,最佳做法是什么?

致以最诚挚的问候,

使用代码示例更新问题

class Interest(models.Model):
    name = models.CharField(_('Name'), max_length=200, )


class UserInterest(models.Model):
    interest = models.ForeignKey(Interest, )
    user = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL'), )
    join_mail_list = models.BooleanField(default=False)

class User(models.Model):
  name = models.CharField(max_length=100)
  interest = models.ManyToManyField(Interest, through='UserInterest', related_name='user_interest')

现在基于上面的模型,当我尝试从User模型创建ModelForm时,我会对MultiSelect字段感兴趣,这是完全正确的。但是,在我的情况下,如果他想为该特定兴趣加入_mail_list,我希望该表单为每个兴趣收集用户兴趣+。请指教?

2 个答案:

答案 0 :(得分:0)

这个问题有点笼统,但我会说,因为它是一个布尔字段,而不是一个多选字段,你有两个 - 一个用于“我感兴趣的东西......”(真)和一个因为“我对...不感兴趣”(假)。两个字段都是从相同的项目列表中进行多选,但是分离允许用户在不注意的情况下应用布尔字段。另外,我强烈建议jQuery UI自动完成,这似乎是最好的选择。

更新回答:

所以看到你的代码有助于清除一些事情。我会这样做的方式就像我在第一时间建议但稍微调整一下。

为每个“兴趣”设置一个简报复选框是笨拙的,因为它要求用户检查“兴趣”两次 - 一次是因为他对它感兴趣而一次因为他想要关于它的电子邮件。因此,您必须自动假设用户想要收到他感兴趣的主题的电子邮件,但允许他们在需要时阻止它。

考虑到这一点,您构建了两个长文本输入,并使用标记系统(here's a good one实现它们,这里是some more)。第一个输入是“我感兴趣”,第二个输入是“我想收到关于......的电子邮件”。然后使用jQuery添加一个事件列表器,确保对于添加到第一个输入的每个标记,它也会自动添加到第二个标记中。然后,如果用户不想收到特定主题(或所有主题)的电子邮件,他可以轻松地将其从第二个输入中删除(这对第一个输入没有任何影响)。

为您举个例子,here's a jsfiddle展示如何使用所选的jQuery库实现这一点。我使用了国家和航运,因为我在所选的图书馆网站上有一个预制列表,所以我只是从那里复制它。正如您所看到的,它是一个非常简单的jQuery代码,您可以轻松地应用于任何其他标记系统(并且非常感谢我自己helped me work that out的优秀RaúlJuárez):

$(".chosen-select").chosen({disable_search_threshold: 10});
$('#countries').on('change', function(e) {
    var selected = $(this).val();
    $.each(selected, function(index, value) {
        $('#shipping option[value="'+value+'"]:first').prop('selected',true);
    });
    $(".chosen-select").trigger('chosen:updated');
});

答案 1 :(得分:0)

我只是假设你想要一个所有兴趣列表,旁边有一个复选框。

让我们假设那些模型:

class Ressource(models.Model):
    name = models.CharField(max_length=255)

class Ressource2Village(models.Model):
    ressource = models.ForeignKey(Ressource)
    village = models.ForeignKey(Village)
    amount = models.FloatField()

class Village(MapObject):
    name = models.CharField(max_length=255)

这种形式:

class Ressoure2VilllageForm(forms.Form):
    name = forms.CharField()
    # you would use a BooleanField
    value = forms.IntegerField()

现在您可以创建一个formset(https://docs.djangoproject.com/en/1.5/topics/forms/formsets/):

from django.forms.formsets import formset_factory
r2v_formset = formset_factory(Ressoure2VilllageForm)

# use boolean for your case, if you want to edit these values later use n2m to initialize value
# [{'name': r2v.ressource.name, 'value': r2v.value} for r2v in your_village.ressource2village.all()]
init_values = [{'name': r.name, 'value': 0} for r in Ressource.objects.all()] 
r2v_formset = r2v_formset(initial=init_values)

模板中的内容会为您提供:

<label for="id_form-0-name">Name:</label><input type="text" name="form-0-name" value="Kohle" id="id_form-0-name">
<label for="id_form-0-value">Value:</label><input type="text" name="form-0-value" value="0" id="id_form-0-value"> 
<label for="id_form-1-name">Name:</label><input type="text" name="form-1-name" value="Eisenerz" id="id_form-1-name">
<label for="id_form-1-value">Value:</label><input type="text" name="form-1-value" value="0" id="id_form-1-value"> 
<label for="id_form-2-name">Name:</label><input type="text" name="form-2-name" value="Golderz" id="id_form-2-name">
[...]

在处理期间,可以考虑到他的身份验证详细信息,与特定用户建立关联。

显示,验证和处理这个应该非常简单,随时可以提出后续问题。