Django:向所有与ForeignKey相关的模型添加对象实例

时间:2018-02-20 10:36:28

标签: jquery django django-models django-forms

我有模特商会

class Chamber(models.Model):
    chamber_name    = models.CharField(max_length=100)

相关模型 ChamberProperty

class ChamberProperty(models.Model):
    chamber         = models.ForeignKey(Chamber, on_delete=models.CASCADE)
    property_name   = models.CharField(max_length=50)
    property_value  = models.CharField(max_length=100, default=None)

现在商会可以有很多 ChamberProperty 。这些要求只是更改为使得如果将 ChamberProperty 添加到 Chamber ,它将被添加到所有未来的 Chamber 实例中,使用空 property_value(默认=无),以便下次加载用于创建新 Chamber 实例的表单时,所有以前的 ChamberProperty.property_name < / strong>在表单中加载,并为空。

示例表格:

第一次创建Chamber实例:

Chamber.chamber_name: Foo
ChamberProperty.property_name: Bar
ChamberProperty.property_value: Baz

第二次创建Chamber实例:

Chamber.chamber_name: Qux
ChamberProperty.property_name: Bar # Old property, retain the name
ChamberProperty.property_value: None # Old property, value empty
ChamberProperty.property_name: Quux # New property, added by a button
ChamberProperty.property_value: 700 # New property, value filled with input box

第三次创建Chamber实例:

Chamber.chamber_name: Corge
ChamberProperty.property_name: Bar # Old property, retain the name
ChamberProperty.property_value: None # Old property, value empty
ChamberProperty.property_name: Quux # Old property, retain the name
ChamberProperty.property_value: None # Old property, value empty
ChamberProperty.property_name: Ouier # New property, added by a button
ChamberProperty.property_value: Grault # New property, value filled with input box

等等。

澄清:如果您使用&#34; ChamberProperty 温度&#34;创建商会A,那么下次创建商会时,商会B,它已经有&#34; ChamberProperty 温度&#34;。然后,你可以向商会B添加一个新的 ChamberProperty ,比如,&#34; Degrees&#34;无论什么价值。然后,如果您创建一个新的 Chamber ,C室,它将具有&#34; ChamberProperty 温度和度数&#34;。

现在我意识到我必须递归地将 ChamberProperty 实例添加到所有其他 Chamber 实例。

使用jQuery脚本在表单中添加了新的属性和值,我已经这样了:

<div class="card loading-card" id="card-loaded">
    <h3 class="card-header bg-primary text-white">
        Add Chamber
    </h3>
    <div class="card-body">
        <form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
            {% csrf_token %}
            {{ properties_formset.management_form }}
        <!-----------Chamber------------>
            <table>
                <tr>
                    <td style="vertical-align:top">
                        <table>
                            <tr>
                                {% for field in chamber_form %}
                                    <td>{{ field|as_crispy_field }}</td>
                                {% endfor %}
                            </tr>
                        </table>
                    </td>
                    <br />
                    <!-----------Chamber Properties------------>
                    <td><p>&nbsp &nbsp &nbsp</p></td>
                    <td>
                        <table class="new-chamber-properties" id="propertiestable">
                        <script type="text/html" id="property-template">
                            <div id="property-__prefix__">
                                <table>
                                    <tr>
                                        {% for field in properties_formset.empty_form %}
                                            <td>{{ field|as_crispy_field }}</td>
                                        {% endfor %}
                                    </tr>
                                </table>
                            </div>
                        </script>

                        <div id="property-form">
                            <tr>
                                {% for properties_form in properties_formset %}
                                    <div id="property-{{ forloop.counter0 }}"></div>
                                {% endfor %}
                            </tr>
                        </div>
                        <tr>
                            <td>
                                <a href="#" id="add-property-button" class="btn btn-outline-primary add-item">Add Properties</a>
                            </td>
                            <td>
                                <a href="#" id="remove-property-button" class="btn btn-outline-danger remove-item">Remove Properties</a>
                            </td>
                            <td><button class="btn btn-primary" type="submit">Submit</button></td>
                        </tr>
                        </table>
                    </td>
                </tr>
            </table>
        </form>
    </div>
</div>

和jQuery:

<script>
    $(document).ready(function () {
        $('.add-item').click(function (ev) {
            ev.preventDefault();
            var count = $('#property-form').children().length;
            console.log(count)
            var tmplMarkup = $('#property-template').html();
            var compiledTmpl = tmplMarkup.replace(/__prefix__/g, count);
            $('div#property-form').append(compiledTmpl);

            // update form count
            $('#id_form-TOTAL_FORMS').attr('value', count + 1);

            // some animate to scroll to view our new form
            $('html, body').animate({ scrollTop: $("#add-property-button").position().top - 200 }, 800);
        });

        for (var i = 0; i < 4; i++) {
            var tmplMarkup = $('#property-template').html();
            var compiledTmpl = tmplMarkup.replace(/__prefix__/g, i);
            $('div#property-form').append(compiledTmpl);
            // update form count
            $('#id_form-TOTAL_FORMS').attr('value', i + 1);
        }
        document.getElementById("id_form-0-property_name").value = "Process";
        document.getElementById("id_form-1-property_name").value = "Type";
        document.getElementById("id_form-2-property_name").value = "Model";
        document.getElementById("id_form-3-property_name").value = "Electrode Diameter";
        document.getElementById("card-loaded").style.visibility = "visible";

        $('.remove-item').click(function (ev) {
            ev.preventDefault();
            var count = $('#property-form').children().length;
            console.log(count);
            if (count > 0) {
                var successCount = count - 1;
                console.log(successCount);
                var formlist = $('#property-form')[0];
                while (count > successCount) {
                    var childNode = formlist.lastChild;
                    formlist.removeChild(childNode);
                    count = $('#property-form').children().length;
                }
                // update form count
                $('#id_form-TOTAL_FORMS').attr('value', count);

                // some animate to scroll to view our new form
                $('html, body').animate({ scrollTop: $("#remove-property-button").position().top - 200 }, 800);
            }
        });
    });
</script>

我不确定如何做到这一点。

我想的也许是,当表单加载时,检索该客户的所有 ChamberProperty 实例,但是如果我将这些值设置为空,它将改变所有其他值的值< strong>商会实例。

对此有何帮助?

1 个答案:

答案 0 :(得分:1)

问题是您当前的模型不能反映您的要求。什么构成属性?显然,它只是名称,而不是它的价值。该值应保存在单独的模型中,而不是与名称和腔室相关联:

class ChamberProperty(models.Model):
    name = models.CharField(max_length=50)

class ChamberPropertyValue(models.Model):
    chamber = models.ForeignKey(Chamber, on_delete=models.CASCADE)
    property = models.ForeignKey(ChamberProperty, on_delete=models.CASCADE)
    value = models.CharField(max_length=100, default=None)

创建新的工作室时,您将立即为数据库中存在的每个ChamberPropertyValue添加一个ChamberProperty。通过这种方式,旧房间将保持其状态具有与其相关联的任何新名称/属性。创建新的chamber后,此代码段应进入您的表单验证:

for prop in ChamberProperty.objects.all():
    ChamberPropertyValue.objects.get_or_create(property=prop, chamber=chamber)