Django在ModelForm中显示来自manytomany关系的字段

时间:2013-08-06 03:42:02

标签: django django-forms

我有一个ModelForm,它有一个ManyToMany字段。我为这个字段创建了一个自定义小部件,继承了CheckboxSelectMultiple。我想在我的ModelForm中显示m2m关系中的字段,而不是用于编辑。对不起,代码缩进就搞砸了。

models.py

class Feed(models.Model):
    name = models.CharField(max_length=200)
    url = models.URLField()
    description = models.TextField(blank=True)
    category = models.ForeignKey('categories.Category', blank=True, null=True)

    def __unicode__(self):
        return self.name

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)

        super(Feed, self).save(*args, **kwargs)


class List(models.Model):
    name = models.CharField(max_length=200)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL)
    feeds = models.ManyToManyField(Feed)
    category = models.ForeignKey('categories.Category', blank=True, null=True)

    def __unicode__(self):
        return self.name

views.py

class ListCreateView(LoginRequiredMixin, UserFormKwargsMixin, FeedsActionMixin,
                     CreateView):
    model = List
    form_class = forms.ListCreateForm

    def get_context_data(self, **kwargs):
        context = super(ListCreateView, self).get_context_data(**kwargs)
        context['form'] = forms.ListCreateForm()
        return context

forms.py

class FeedListWidget(forms.CheckboxSelectMultiple):
    class Media:
        css = {
            'all': ('css/feed_list_style.css',)
        }
        js = ('js/feed_list.js')

    def __init__(self, attrs={}):
        super(FeedListWidget, self).__init__(attrs)

        feeds = Feed.objects.all()
        classes = tuple([(c.id, c.name, c.description) for c in feeds])
        self.choices = classes

    def render(self, name, value, attrs=None, choices=()):
        output = super(FeedListWidget, self).render(name, values, attrs, choices)
        return output


class ListCreateForm(UserKwargModelFormMixin, forms.ModelForm):
    feeds = forms.ModelMultipleChoiceField(
                queryset=Feed.objects.all(), widget=FeedListWidget())

    class Meta:
        model = List
        fields = ['name','feeds']
        widgets = {
            'name': forms.TextInput,
            'feeds': FeedListWidget,
        }

    def __init__(self, *args, **kwargs):
        super(ListCreateForm, self).__init__(*args, **kwargs)

        owner = self.user
        self.helper = FormHelper(self)
        self.helper.form_method = 'POST'
        self.helper.layout = Layout(
            Fieldset(
                '',
                HTML("""
                    <p>Create a List here</p>
                """),
                'name',
            ),
            Field('feeds', template="feeds/feeds_select.html"),
        )
        self.helper.add_input(Submit('save', 'save'))

        return super(ListCreateForm, self).__init__(*args, **kwargs)

    def save(self, commit=True):
        list = super(ListCreateForm, self).save(commit=False)
        list.owner = self.user

        if commit:
            list.save()
            self.save_m2m()

        return list

feeds_select.html

{% load debug_tags %}
<div class="controls"{% if flat_attrs %} {{ flat_attrs|safe }}{% endif %}>
{% include 'bootstrap/layout/field_errors_block.html' %}

{% for choice in field.field.choices %}
<div class="feed row">
    <div class="feed-icon span1"></div>
    <div class="feed-name span5">{{ choice.1 }}
        <div class="feed-description"></div>
    </div>
    <div class="description-toggle span2">See More</div>
    <label class="checkbox{% if inline_class %} {{ inline_class }}{% endif %} span1">
        <div class="add-btn">Add</div>
        <input type="checkbox"{% if choice.0 in field.value or choice.0|stringformat:"s" in field.value or choice.0|stringformat:"s" == field.value|stringformat:"s" %} checked="checked"{% endif %} name="{{ field.html_name }}" id="id_{{ field.html_name }}_{{ forloop.counter }}" value="{{ choice.0 }}">
    </label>
</div>
{% endfor %}

{% include 'bootstrap/layout/help_text.html' %}
</div>

注意我使用django-crispy-forms来处理表单布局,不确定这是否会影响任何内容。所以在我的ListCreateForm上,我想访问Feed的描述及其名称。有没有办法让我从“field.field.choices”变量访问它?我知道我可以将它包含在我的模型unicode函数中,但我希望将其作为模板标记访问,因为我将使用jquery隐藏/显示它。

我是以错误的方式来做这件事的吗?我无法找到与此直接相关的任何问题,并且很难拼凑出有关模型及其操作的答案。非常感谢任何帮助或指导。

0 个答案:

没有答案