首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django -自定义ModelMultipleChoiceField不能根据父模型对选择进行分类。

Django -自定义ModelMultipleChoiceField不能根据父模型对选择进行分类。
EN

Stack Overflow用户
提问于 2019-01-20 20:44:23
回答 1查看 946关注 0票数 0

编辑可在下面!

我的目标:

Category1

-备选案文1

-第2段

-第3段

Category2

-备选案文1

-第2段

等。

我有一个家长模型(场地)和一个儿童模型(舒适)。一个场地可以有许多便利设施。

当配置我的初始数据并以{{form.as_p}}表示它时,一切都按预期工作。

,但是当我尝试呈现我自己的自定义表单,以便可以应用一个循环时,它不会预先填充它们.

这是我的模板:

代码语言:javascript
复制
<form method="POST" class="ui form">
    {% csrf_token %}
    {% for category in categories %}
    <h4 class="ui horizontal divider header">
        <i class="list icon"></i>
        {{category.category}}
    </h4>
    <p class="ui center aligned text"><u>{{category.description}}</u></p>

    {% for amenity in category.amenity_set.all %}

    <div class="inline field">
        <label for="choices_{{amenity.id}}"></label>
        <div class="ui checkbox">
            <input id="choices_{{amenity.id}}" type="checkbox" value="{{amenity.id}}" name="choices">

            <label><span data-tooltip="{{amenity.description}}" data-position="top left">{{amenity}}</span></label>
        </div>

    </div>
    {% endfor %}
    {% endfor %}
    <button type="submit" name="submit" class="ui button primary">Next</button>
</form>

我的ModelForm:

代码语言:javascript
复制
class AmenitiesForm(ModelForm):
    class Meta:
        model = Venue
        fields = ('choices',)


    choices = forms.ModelMultipleChoiceField(Amenity.objects.all(), widget=forms.CheckboxSelectMultiple,)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if kwargs.get('instance'):
            initial = kwargs.setdefault('initial', {})
            initial['choices'] = [c.pk for c in kwargs['instance'].amenity_set.all()]

        forms.ModelForm.__init__(self, *args, **kwargs)

    def save(self, commit=True):
        instance = forms.ModelForm.save(self)
        instance.amenity_set.clear()
        instance.amenity_set.add(*self.cleaned_data['choices'])
        return instance

我的views.py:

代码语言:javascript
复制
class AddAmenitiesView(LoginRequiredMixin, CreateView):
    """
    AddAmenitiesView is the view that prompts the user to select the amenities of their venue.
    """
    model = Venue
    form_class = AmenitiesForm
    template_name = 'venues/add_amenities.html'

    def parent_venue(self):
        """
        returns the parent_venue based on the kwargs
        :return:
        """
        parent_venue = Venue.objects.get(id=self.kwargs["venue_id"])
        return parent_venue

    def get_initial(self):
        initial = super().get_initial()
        initial['choices'] = self.parent_venue().amenity_set.all()
        return initial

    def form_valid(self, form):
        venue = Venue.objects.get(id=self.kwargs['venue_id'])
        form.instance = venue
        # form.instance.owner = self.request.user
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["parent_venue"] = self.parent_venue()
        context["categories"] = AmenitiesCategory.objects.all()
        return context

    def get_success_url(self):
        return reverse('add-amenities', kwargs={'venue_id': self.object.id,})

我认为它与我的模板有关,因为通常呈现表单,它会预先填充模型。

谢谢你抽出时间来!

编辑:使用Raydel Miranda的答案的--我设法编辑了表单显示方式的模板:

forms.py:

代码语言:javascript
复制
class CustomAmenitiesSelectMultiple(CheckboxSelectMultiple):
    """
    CheckboxSelectMultiple Parent: https://docs.djangoproject.com/en/2.1/_modules/django/forms/widgets/#CheckboxSelectMultiple
    checkbox_select.html: https://github.com/django/django/blob/master/django/forms/templates/django/forms/widgets/checkbox_select.html
    multiple_input.html: https://github.com/django/django/blob/master/django/forms/templates/django/forms/widgets/multiple_input.html
    checkbox_option.html: https://github.com/django/django/blob/master/django/forms/templates/django/forms/widgets/checkbox_option.html
    input_option.html: https://github.com/django/django/blob/master/django/forms/templates/django/forms/widgets/input_option.html

    """
    template_name = "forms/widgets/custom_checkbox_select.html"
    option_template_name = 'forms/widgets/custom_checkbox_option.html'


class AmenitiesForm(ModelForm):
    class Meta:
        model = Venue
        fields = ('choices',)

    choices = forms.ModelMultipleChoiceField(Amenity.objects.all(), widget=CustomAmenitiesSelectMultiple,)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if kwargs.get('instance'):
            initial = kwargs.setdefault('initial', {})
            initial['choices'] = [c.pk for c in kwargs['instance'].amenity_set.all()]

        forms.ModelForm.__init__(self, *args, **kwargs)

    def save(self, commit=True):
        instance = forms.ModelForm.save(self)
        instance.amenity_set.clear()
        instance.amenity_set.add(*self.cleaned_data['choices'])
        return instance

custom_checkbox_select.html:

代码语言:javascript
复制
{% with id=widget.attrs.id %}
<div class="inline field">
    <div {% if id %} id="{{ id }}" {% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}" {% endif %}>
        {% for group, options, index in widget.optgroups %}{% if group %}
        <div>
            {{ group }}
            <div>
                {% if id %} id="{{ id }}_{{ index }}" {% endif %}>{% endif %}{% for option in options %}
                <div class="checkbox">{% include option.template_name with widget=option %}</div>
                {% endfor %}{% if group %}
            </div>

        </div>
        {% endif %}{% endfor %}
    </div>
</div>

{% endwith %}

custom_checkbox_option.html:

代码语言:javascript
复制
<label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %}>{% endif %}{% include "django/forms/widgets/input.html" %}{% if widget.wrap_label %} {{ widget.label }}</label>

根据请求,也是我的models.py:

代码语言:javascript
复制
class TimeStampedModel(models.Model):
    """
    An abstract base class model that provides self-updating
    "created" and "modified" fields.
    """

    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True


class VenueType(TimeStampedModel):
    type = models.CharField(max_length=250)
    description = models.TextField()

    def __str__(self):
        return self.type


class Venue(TimeStampedModel):
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=250)
    type = models.ForeignKey(VenueType, on_delete=models.CASCADE)
    total_capacity = models.PositiveIntegerField(default=0)
    description = models.TextField(blank=False)
    contact_number = PhoneNumberField(blank=True)
    contact_email = models.EmailField(blank=True)
    published = models.BooleanField(default=False)

    def __str__(self):
        return self.name

class AmenitiesCategory(TimeStampedModel):
    category = models.CharField(max_length=250)
    description = models.TextField()

    def __str__(self):
        return self.category


class Amenity(TimeStampedModel):
    category = models.ForeignKey(AmenitiesCategory, on_delete=models.CASCADE)
    venues = models.ManyToManyField(Venue, blank=True)
    space = models.ManyToManyField(Space, blank=True)
    name = models.CharField(max_length=250)
    description = models.TextField()

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['category']
EN

回答 1

Stack Overflow用户

发布于 2019-01-20 21:11:05

您说过,在配置我的初始数据并以{{form.as_p}}表示数据时,一切都按预期工作,如果是,请使用{ form.choices }}来呈现该字段。

代码语言:javascript
复制
<form method="POST" class="ui form">
    {% csrf_token %}  
    {{form.choices}}
   <button type="submit" name="submit" class="ui button primary">Next</button>
</form>

然后,您需要的是拥有一个带有自己的模板的自定义CheckboxSelectMultiple (如果您希望向用户提供自定义表示),并在您的表单中使用它:

自定义CheckboxSelectMultiple可以是:

代码语言:javascript
复制
class MyCustomCheckboxSelectMultiple(CheckboxSelectMultiple):
    template_name = "project/template/custom/my_checkbox_select_multiple.html"

并以下列形式:

代码语言:javascript
复制
class AmenitiesForm(ModelForm):
    # ... 
    choices = forms.ModelMultipleChoiceField(Amenity.objects.all(), widget=forms.MyCustomCheckboxSelectMultiple)
    # ...

如何实现模板my_checkbox_select_multiple.html,取决于您。

如果您在1.11之前使用了一些Django,请访问此链接,了解要定制小部件模板所必须做的其他事情。

Django widget override template

希望能帮上忙!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54280796

复制
相关文章

相似问题

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