【问题标题】:Django - Data is not submitted to my database, but no errorDjango - 数据未提交到我的数据库,但没有错误
【发布时间】:2021-10-04 01:59:08
【问题描述】:

我正在创建一个系统,通过让用户添加所有者的姓名来跟踪不同电话公司的所有者。我希望用户能够一次添加多个所有者,并且希望避免使用大量 RegEx、Ajax 和 Node,我在我的数据库中创建了 5 个“所有者”表(意大利面条代码的缩影,我知道)。最后 4 个 Owner 表具有 null=True 和 blank=True,因此它们是可选的。在 UI 中显示此内容时,我将所有者的每个表单字段表示形式放在其自己的 div 中并隐藏最后 4 个 div。用户可以通过单击按钮选择“添加另一个所有者”,最多可添加 4 个额外所有者。很少会填写所有五个 div,因此其中一些始终被基本的 javascript 隐藏。然后我继续使用 .save() 像任何其他模型一样保存所有这些。当用户填写完所有需要的字段并点击“提交”时,一切正常,但是......数据永远不会发送到数据库。

我在任何地方都没有错误,这导致我猜测我在保存数据时传入的表单无效。我知道问题出在“几个隐藏的表单”部分,因为当我只有 1 个所有者表并且没有任何隐藏时,我的系统运行良好。但是,由于它没有给我任何错误消息,我现在不知道我能做什么 - 我不知道为什么它认为我的表单无效。

注意:我意识到 django 的方式是制作表单集以添加一个表的多个实例,但是使这些动态化并隐藏,例如,表单集中的 5 个表单中的 4 个,并在单击按钮或真正的动态表单时显示其余的表单循环的行为非常具有挑战性,我没有 javascript/react 知识来做到这一点。隐藏表单并根据用户请求显示它的能力很重要 - 我知道它可以很容易地解决,否则只需使用表单集而不隐藏任何内容。

编辑: 我尝试了一些方法来修复它,例如在表单名称和 .save() 之间添加 .instance,设置 instance =(我正在编辑其实例的表单)然后 commit=False,并设置 commit=True在最后保存。我制作的新“实例”变量变灰并显示“未使用局部变量“实例”值。

我在我的models.py 文件中发现了一个错误:在PhoneCompany 中,owner_Set 应该是一个ForeignKey,但实际上写成一个ManyToManyField。当我更正它时,它返回以下错误:django.db.utils.IntegrityError: NOT NULL constraint failed: new__phoneBook_companyinformation.owner_set_id 我想这并不奇怪;由于数据从未保存到数据库中,因此没有创建所有者集,因此没有可引用的所有者集。

我的 models.py 文件:

from django.db import models


Owner1(models.Model):
    owner1_name = models.CharField(max_length=200)

Owner2(models.Model):
    owner2_name = models.CharField(max_length=200)

Owner3(models.Model):
    owner3_name = models.CharField(max_length=200)

Owner4(models.Model):
    owner4_name = models.CharField(max_length=200)

Owner5(models.Model):
    owner5_name = models.CharField(max_length=200)

OwnerSet(models.Model):
    owner1 = models.ForeignKey(Owner1, on_delete=models.CASCADE, default=None)
    owner2 = models.ForeignKey(Owner2, on_delete=models.CASCADE, default=None)
    owner3 = models.ForeignKey(Owner3, on_delete=models.CASCADE, default=None)
    owner4 = models.ForeignKey(Owner4, on_delete=models.CASCADE, default=None)
    owner5 = models.ForeignKey(Owner5, on_delete=models.CASCADE, default=None)

PhoneCompany(models.Model):
    name = models.CharField(max_length = 400, default=None)
    address = models.CharField(max_length = 400, default=None)
    owner_set = models.ForeignKey(OwnerSet, on_delete=models.CASCADE, default=None)

我的 forms.py 文件:

from django.forms import ModelForm
from django import forms
from .models import *


class Form1(ModelForm):
    class Meta:
        model = Owner1
        fields = ['owner1_name']

        widgets = {
            'owner1_name': TextInput(attrs={'class': 'form-control', 'id': 'owner1'})}


class Form2(ModelForm):
    class Meta:
        model = Owner2
        fields = ['owner2_name']

        widgets = {
            'owner2_name': TextInput(attrs={'class': 'form-control', 'id': 'owner2'})}


class Form3(ModelForm):
    class Meta:
        model = Owner3
        fields = ['owner3_name']

        widgets = {
            'owner3_name': TextInput(attrs={'class': 'form-control', 'id': 'owner3'})}


class Form4(ModelForm):
    class Meta:
        model = Owner4
        fields = ['owner4_name']

        widgets = {
            'owner4_name': TextInput(attrs={'class': 'form-control', 'id': 'owner4'})}


class Form5(ModelForm):
    class Meta:
        model = Owner5
        fields = ['owner5_name']

        widgets = {
            'owner5_name': TextInput(attrs={'class': 'form-control', 'id': 'owner5'})}


class Form6(ModelForm):
    class Meta:
        model = OwnerSet
        fields = ['owner1_name']  
        # because i needed at least one to make the code run and it didn't like like '__all__'

        widgets = {
            'owner1_name': iTextInput(attrs={'class': 'form-control', 'id': 'fk_owner1'})}


class Form7(ModelForm):
    class Meta:
        model = PhoneCompany
        fields = ['name', 'address']

        widgets = {
            'name': TextInput(attrs={'class': 'form-control', 'id': 'comp_name'})
            'address': TextInput(attrs={'class': 'form-control', 'id': 'adrs'})
        }

我的views.py 文件:

from django.shortcuts import render, redirect
from .forms import *

def company_input(request):
    form1 = Form1()  
    form2 = Form2() 
    form3 = Form3()  
    form4 = Form4()  
    form5 = Form5()  
    form6 = Form6() 
    form7 = Form7()

    if request.method == 'POST':
        form_owner1 = Form1(request.POST)
        form_owner2 = Form2(request.POST)
        form_owner3 = Form3(request.POST)
        form_owner4 = Form4(request.POST)
        form_owner5 = Form5(request.POST)
        form_ownerset = Form6(request.POST)
        form_company = Form7(request.POST)

        if form_owner1.is_valid() and form_owner2.is_valid() and 
        form_owner3.is_valid() and form_owner4.is_valid() and 
        form_owner5.is_valid() and form_ownerset.is_valid() and 
        form_company.is_valid():
            owner1 = form_owner1.save()
            owner2 = form_owner2.save()
            owner3 = form_owner3.save()
            owner4 = form_owner4.save()
            owner5 = form_owner5.save()

            instance = form_ownerset.save(commit=False) # greys out
            instance.owner1 = owner1
            instance.owner2 = owner2
            instance.owner3 = owner3
            instance.owner4 = owner4
            instance.owner5 = owner5
            ownerset = instance.save(commit=True)

            instance = form_company.save(commit=False)  # greys out
            instance.ownerset = ownerset
            company = instance.save()
        else: 
            print("Error: a form is not valid.")  # never returns the error...

    context = {'from1': form1,
               'form2': form2,
               'form3': form3,
               'form4': form4,
               'form5': form5,
               'form6': form6,
               'form7': form7,
               }
    return render(request, 'phoneBook/reg_owners.html', context)

我的 reg_owners.html 文件:

            <div id="owners" class="column">
                <div id="owner1">
                    <h5>Owner 1:</h5>
                    <br>
                    {{ form1.as_p }}
                </div>

                <div id="masterdiv">
                    <button id="btn1" style="width: 90px; margin-left: 40px" >Add Owner</button>
                    <div id="own2" style="display: none; margin-left: 40px; border-radius: 6px;">
                        <p>{{ form2.as_p }}</p>
                    </div>

                    <br>

                    <button id="btn2" style="margin-left: 40px; display: none">Add Owner</button>
                    <div id="own3" style="display: none; margin-left: 40px; border-radius: 6px;">
                        <p>{{ form3.as_p }}</p>
                    </div>

                    <br>

                    <button id="btn3" style="margin-left: 40px; display: none">Add Owner</button>
                    <div id="own4" style="display: none; margin-left: 40px; border-radius: 6px;">
                        <p>{{ form4.as_p }}</p>
                    </div>

                    <br>

                    <button id="btn4" style="margin-left: 40px; display: none">Add Owner</button>
                    <div id="own5" style="display: none; margin-left: 40px; border-radius: 6px;">
                        <p>{{ form5.as_p }}</p>
                    </div>

                </div>

我的 add_owner.js 文件:

const btn1 = document.getElementById("btn1")
const btn2 = document.getElementById("btn2")
const btn3 = document.getElementById("btn3")
const btn4 = document.getElementById("btn4")

# own1 is not included, because the first owner form is required and never changes or hides
const own2 = document.getElementById("own2")
const own3 = document.getElementById("own3")
const own4 = document.getElementById("own4")
const own5 = document.getElementById("own5")

btn1.onclick = function(e){
    e.preventDefault();
    if(btn1.innerHTML === "Add Owner"){
        btn1.innerHTML = "Remove";
        if(btn2.style.display === "none" && own2.style.display === "none"){
            btn2.style.display = "block";
            own2.style.display = "block";
        }
        else if (btn2.style.display === "block" && own2.style.display === "block"){
            btn2.style.display = "none";
            own2.style.display = "none";
        }
    }
    /*close the div*/
    else{
        btn1.innerHTML = "Add Owner"
        if(own2.style.display === "block" && btn2.style.display === "block"){
            own2.style.display = "none"
            btn2.style.display = "none"
        }
    }

}

btn2.onclick = function(e){
    e.preventDefault();
    if(btn2.innerHTML === "Add Owner"){
        btn2.innerHTML = "Remove";
        btn1.disabled = true
        /*Display button 3 and owner 3*/
        if(btn3.style.display === "none" && own3.style.display === "none"){
            btn3.style.display = "block";
            own3.style.display = "block";
        }  /*hide button 3 and owner 3*/
        else if (btn3.style.display === "block" && own3.style.display === "block"){
            btn3.style.display = "none";
            own3.style.display = "none";
        }
    }
    /*close the div*/
    else{
        btn2.innerHTML = "Add Owner"
        if(own3.style.display === "block" && btn3.style.display === "block"){
            own3.style.display = "none"
            btn3.style.display = "none"
            btn1.disabled = false
        }
    }
}

btn3.onclick = function(e){
    e.preventDefault();
    if(btn3.innerHTML === "Add Owner"){
        btn3.innerHTML = "Remove";
        btn2.disabled = true
        /*Display button 3 and owner 3*/
        if(btn4.style.display === "none" && own4.style.display === "none"){
            btn4.style.display = "block";
            own4.style.display = "block";
        }  /*hide button 3 and owner 3*/
        else if (btn4.style.display === "block" && own4.style.display === "block"){
            btn4.style.display = "none";
            own4.style.display = "none";
        }
    }
    /*close the div*/
    else{
        btn3.innerHTML = "Add Owner"
        if(own4.style.display === "block" && btn4.style.display === "block"){
            own4.style.display = "none"
            btn4.style.display = "none"
            btn2.disabled = false
        }
    }
}


btn4.onclick = function(e){
    e.preventDefault();
    if(btn4.innerHTML === "Add Owner"){
        btn4.innerHTML = "Remove";
        btn3.disabled = true
        if(own5.style.display === "none"){
            own5.style.display = "block";
        }  /*hide button 3 and author 3*/
        else if (own5.style.display === "block"){
            own5.style.display = "none";
        }
    }
    /*close the div*/
    else{
        btn4.innerHTML = "Add iOwner"
        if(own5.style.display === "block"){
            own5.style.display = "none"
            btn3.disabled = false
        }
    }
}

【问题讨论】:

  • 您需要在form_ownerset.instance 上致电save,因为您更改了instance。所以form_ownerset.instance.save()
  • 我尝试了您的两个建议,但它们没有任何作用
  • 你也可以试试form_company吗?
  • 是的。虽然它看起来像 instance = 技巧永远不会起作用 - 它只是变灰并说“未使用局部变量'instance'值”
  • 我在任何地方都添加了 form_(x).instance.save() 我现在改变了一个实例,没有区别

标签: javascript python html django django-forms


【解决方案1】:
            form_ownerset.instance.owner1 = owner1
            form_ownerset.instance.owner2 = owner2
            form_ownerset.instance.owner3 = owner3
            form_ownerset.instance.owner4 = owner4
            form_ownerset.instance.owner5 = owner5

完成上述所有操作后,调用:

            form_ownerset.instance.save()

如果还是不行,先尝试保存表单,不提交获取实例,然后编辑,保存:

            instance = form_ownerset.save(commit=False)
            instance.owner2 = owner2
            instance.owner3 = owner3
            instance.owner4 = owner4
            instance.owner5 = owner5
            instance.save()

或者说得更清楚:

            ownerset = form_ownerset.save(commit=False)
            ownerset.owner1 = owner1
            ownerset.owner2 = owner2
            ownerset.owner3 = owner3
            ownerset.owner4 = owner4
            ownerset.owner5 = owner5
            ownerset.save()

            company = form_company.save(commit=False)
            company.ownerset = ownerset
            company.save()

【讨论】:

    【解决方案2】:

    问题在于我的 OwnerSet 功能。在 forms.py 中,我定义了我希望 owner1_id 成为一个字段,但我从未真正将任何数据传递到该字段中或根本没有真正使用过它。每当我尝试提交数据时,这都会在命令终端中引发验证错误,这会擦除 POST 请求,因此没有数据要发送到数据库。删除 forms.py 中的 OwnerSet 表单并将所有 owner_ids 路由到 views.py 中的公司修复了问题,并且数据再次提交到我的数据库。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-09
      • 1970-01-01
      • 1970-01-01
      • 2019-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      相关资源
      最近更新 更多