Django如何动态生成表单集?

我想通过每次点击“Ajouter un point”按钮,就可以向ZHDrag表单动态添加一行Longitude参数和Latitude参数,用户可以自行输入数据并保存。
其中Longitude和Latitude存储在ZHDragPoint类中,ZHDrag是ZHDragPoint的外键。

forms.py

class ZHDragForm(forms.ModelForm):

    class Meta:
        model = ZHDrag
        fields = '__all__'

    @property
    def helper(self):
        helper = CoreFormHelper()

        details = [
            ['port', 'zhd_code', ],
            ['zhd_nom', 'zhd_nom_precedent', ],
            'zh_drag_donnee_geo_set',
        ]

        centroide = [
            ['zhd_long_centroide', 'zhd_lat_centroide', ],
        ]

        helper.layout = Layout(
            CoreFormHelper.format_fieldset(_('Détails'), details),
            CoreFormHelper.format_fieldset(_('Coordonnées du centroïde'), centroide),
            Fieldset(
                _("Coordonnées des sommets de l'emprise"),
                StrictButton("Ajouter un point", name="ajouter_un_point", value="Ajouter un point", id="ajouter_un_point", css_class="btn-primary"),
            ),
        )

        return helper

html界面

{% extends "layouts/base.html" %}

{% load i18n core_tags %}

{# Translators: Zones homogènes de dragage head title #}
{% block title %} {% trans "Zones homogènes de dragage" %} {% endblock %} 

<!-- Element injected in the BODY element -->
{% block body_class %} sidebar-mini {% endblock body_class %} 

<!-- Specific Page CSS goes HERE  -->
{% block stylesheets %}
{% endblock stylesheets %}


{% block content %}    

  {# Translators: Formulaire Zones homogènes de dragage title #}
  {% trans "Zones homogènes de dragage" as title %}

  {# Translators: Formulaire Modification d'une zone homogène de dragage card title #}
  {% trans "Modification d'une zone homogène de dragage" as card_title %}

  {# Translators: Url Retour à la liste #}
  {% url 'zh-drag-list' as return_button_url %}

  {% show_header_title title %}

  {% show_card_form card_title form return_button_url=return_button_url %}

{% endblock content %}

<!-- Specific Page JS goes HERE  -->
{% block javascripts %}
{% endblock javascripts %}


models.py

class ZHDrag(models.Model):
    zhd_nom = models.CharField(_('nom'), max_length=100)
    zhd_code = models.CharField(_('code'), max_length=100)
    zhd_long_centroide = models.FloatField(_('longitude centroide'), max_length=100, null=True, blank=True)
    zhd_lat_centroide    = models.FloatField(_('latitude centroide'), max_length=100, null=True, blank=True)
    zhd_nom_precedent = models.CharField(_('nom précédent'), max_length=100)

    port = models.ForeignKey(
        Port,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('port')
    )

    zh_drag_donnee_geo_set = models.ManyToManyField(
        ZHDragDonneeGeo,
        verbose_name=_("Formats des données géographiques disponibles (plusieurs choix possibles)")
    )

    def __str__(self):
        return self.zhd_nom
    
    class Meta:
        ordering = ('zhd_nom',)


class ZHDragPoint(models.Model):
    zhd_long = models.FloatField(_('longitude'), max_length=100, null=True, blank=True)
    zhd_lat = models.FloatField(_('latitude'), max_length=100, null=True, blank=True)

    zh_drag = models.ForeignKey(
        ZHDrag,
        on_delete=models.CASCADE,
        verbose_name=_('zh drag')
    )

    def __str__(self):
        return '(long:' + str(self.zhd_long) + ',lat:' + str(self.zhd_lat) + ')'


views.py

class ZHDragUpdateView(SupervisorRequiredMixin, UpdateView):
    model = ZHDrag
    template_name = 'bdd_dragage/administration/zh-drag-update.html'
    form_class = ZHDragForm
    success_url = reverse_lazy('zh-drag-list')

自己用javascript写
使用jQuery
模板

<h3>My Services</h3>
{{ serviceFormset.management_form }}
{% for form in serviceFormset.forms %}
    <div class='table'>
    <table class='no_error'>
        {{ form.as_table }}
    </table>
    </div>
{% endfor %}
<input type="button" value="Add More" id="add_more">
<script>
    $('#add_more').click(function() {
        cloneMore('div.table:last', 'service');
    });
</script>


javascript

function cloneMore(selector, type) {
    var newElement = $(selector).clone(true);
    var total = $('#id_' + type + '-TOTAL_FORMS').val();
    newElement.find(':input').each(function() {
        var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
        var id = 'id_' + name;
        $(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
    });
    newElement.find('label').each(function() {
        var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');
        $(this).attr('for', newFor);
    });
    total++;
    $('#id_' + type + '-TOTAL_FORMS').val(total);
    $(selector).after(newElement);
}

cloneMore接受selector作为第一个参数,formset的类型作为第二个参数。

一个用于管理 Django 表单集的 jQuery 插件
这个jQuery插件通过允许客户端在客户端添加和删除表单来帮助您创建更多可用的Django表单集。
https://github.com/elo80ka/django-dynamic-formset


django formset 文档
https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#model-formsets
使用 jquery 和 django formset 实现动态表单

https://github.com/javisantana/django-dinamyc-form

https://download.csdn.net/download/weixin_38750721/13769495?spm=1005.2026.3001.5635&utm_medium=distribute.pc_relevant_ask_down.none-task-download-2~default~OPENSEARCH~Rate-4.pc_feed_download_top3ask&depth_1-utm_source=distribute.pc_relevant_ask_down.none-task-download-2~default~OPENSEARCH~Rate-4.pc_feed_download_top3ask