Django - 数据没有提交到我的数据库,但没有错误

Django - Data is not submitted to my database, but no error

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

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

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

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

显示为灰色

我在我的 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.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()

问题出在我的 OwnerSet 功能上。在 forms.py 中,我定义了我希望 owner1_id 成为一个字段,但我从未真正将任何数据传递到该字段中,也从未真正使用过它。每当我尝试提交数据时,这都会在命令终端中抛出一个 validationError,这会擦除 POST 请求,因此没有数据可以发送到数据库。删除 forms.py 中的 OwnerSet 表单并将所有 owner_ids 路由到 views.py 中的公司解决了这个问题,数据再次提交到我的数据库。