Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在Django中通过modelformset_工厂验证?_Python_Django_Django Forms - Fatal编程技术网

Python 如何在Django中通过modelformset_工厂验证?

Python 如何在Django中通过modelformset_工厂验证?,python,django,django-forms,Python,Django,Django Forms,我有两个一对一关系的模型,如下所示 class Kategori(models.Model): urun = models.CharField(db_column='Urun', max_length=255, blank=True, null=True) # Field name made lowercase. kategori = models.CharField(db_column='Kategori', max_length=255, blank=True, null=

我有两个一对一关系的模型,如下所示

class Kategori(models.Model):
    urun = models.CharField(db_column='Urun', max_length=255, blank=True, null=True)  # Field name made lowercase.
    kategori = models.CharField(db_column='Kategori', max_length=255, blank=True, null=True)  # Field name made lowercase.
    ust_kategori = models.CharField(db_column='Ust_Kategori', max_length=255, blank=True, null=True)  # Field name made lowercase.
    urun_adi = models.CharField(db_column='URUN_ADI', max_length=255, blank=True, null=True)  # Field name made lowercase.
    ur_id = models.CharField(db_column='UR_ID', max_length=255, blank=True, null=True)  # Field name made lowercase.
    marka = models.CharField(db_column='MARKA', max_length=255, blank=True, null=True)  # Field name made lowercase.
    cesidi = models.CharField(db_column='CESIDI', max_length=255, blank=True, null=True)  # Field name made lowercase.
    miktar = models.FloatField(db_column='MIKTAR', blank=True, null=True)  # Field name made lowercase.
    birim = models.CharField(db_column='BIRIM', max_length=255, blank=True, null=True)  # Field name made lowercase.
    adet = models.FloatField(db_column='ADET', blank=True, null=True)  # Field name made lowercase.

class categoryprob(models.Model):
    urun = models.OneToOneField(Kategori,on_delete=models.CASCADE,related_name="prob")
    kategori = models.CharField(max_length=255, blank=True, null=True)  # Field name made lowercase.
    ust_kategori = models.CharField(max_length=255, blank=True, null=True)  # Field name made lowercase.
    urun_adi = models.CharField(max_length=255, blank=True, null=True)  # Field name made lowercase.
    marka = models.CharField(max_length=255, blank=True, null=True)  # Field name made lowercase.
    cesidi = models.CharField(max_length=255, blank=True, null=True)  # Field name made lowercase.
    miktar = models.FloatField(blank=True, null=True)  # Field name made lowercase.
    birim = models.CharField(max_length=255, blank=True, null=True)  # Field name made lowercase.
    adet = models.FloatField(blank=True, null=True)  # Field name made lowercase.

我正在尝试更新
Kategori
模型对象,这些对象依赖于
categoryprob
输入。我准备了一个表格,根据对象在
categoryprob
的概率获取
Kategori
对象,如下所示

from django import forms
from mailservice.models import categoryprob,Kategori 

PASS_PROB = 0.8

class predictionForm(forms.ModelForm):
    
    class Meta:
        model = Kategori
        fields = ["urun","kategori","ust_kategori","urun_adi","marka","cesidi","miktar","birim","adet"]
        
        widgets = {
            'kategori': forms.Select(choices=set(Kategori.objects.all().values_list('kategori','kategori'))),
            'ust_kategori': forms.Select(choices=set(Kategori.objects.all().values_list('ust_kategori','ust_kategori'))),
            'marka': forms.Select(choices=set(Kategori.objects.all().values_list('marka','marka'))),
            'cesidi': forms.Select(choices=set(Kategori.objects.all().values_list('cesidi','cesidi'))),
            'miktar': forms.Select(choices=set(Kategori.objects.all().values_list('miktar','miktar'))),
            'birim': forms.Select(choices=set(Kategori.objects.all().values_list('birim','birim'))),
            'adet': forms.Select(choices=set(Kategori.objects.all().values_list('adet','adet'))),
        }
        
        labels ={
            'urun':""
        }

    def __init__(self, *args, **kwargs):
        super(predictionForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        prob = categoryprob.objects.get(urun=instance)

        self.fields['urun'].widget.attrs['readonly'] = True

        if float(prob.kategori) > PASS_PROB:
            self.fields['kategori'].widget.attrs['disabled'] = True
            self.fields['kategori'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['kategori'].widget.attrs['style'] = 'border-color:green'

        if float(prob.ust_kategori) > PASS_PROB:
            self.fields['ust_kategori'].widget.attrs['disabled'] = True
            self.fields['ust_kategori'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['ust_kategori'].widget.attrs['style'] = 'border-color:green'
        
        if float(prob.urun_adi) > PASS_PROB:
            self.fields['urun_adi'].widget.attrs['disabled'] = True
            self.fields['urun_adi'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['urun_adi'].widget.attrs['style'] = 'border-color:green'
        
        if float(prob.marka) > PASS_PROB:
            self.fields['marka'].widget.attrs['disabled'] = True
            self.fields['marka'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['marka'].widget.attrs['style'] = 'border-color:green'
        
        if float(prob.cesidi) > PASS_PROB:
            self.fields['cesidi'].widget.attrs['disabled'] = True
            self.fields['cesidi'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['cesidi'].widget.attrs['style'] = 'border-color:green'

        if float(prob.miktar) > PASS_PROB:
            self.fields['miktar'].widget.attrs['disabled'] = True
            self.fields['miktar'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['miktar'].widget.attrs['style'] = 'border-color:green'
        
        if float(prob.birim) > PASS_PROB:
            self.fields['birim'].widget.attrs['disabled'] = True
            self.fields['birim'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['birim'].widget.attrs['style'] = 'border-color:green'
        
        if float(prob.adet) > PASS_PROB:
            self.fields['adet'].widget.attrs['disabled'] = True
            self.fields['adet'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['adet'].widget.attrs['style'] = 'border-color:green'


<form method="post" enctype="multipart/form-data">
    
    <div class="form-row">
        {{ p_form.management_form }}
        {% csrf_token %}
        {%for form in p_form%}
        <div class="form-group col-md-12">
            <div class="card">
                <div class="card-header">
                    {{form.urun|as_crispy_field}}
                </div>
                <div class="card-body">
                    
                    <div class="row">   
                        <div class ="col-md-3 col ">
                            {{form.kategori|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.ust_kategori|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.urun_adi|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.marka|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.cesidi|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.miktar|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.birim|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.adet|as_crispy_field}}
                        </div>
                        
                    </div>
                    
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
    
    <button type="submit" class="btn btn-success">Kaydet</button>
</form>
我使用
modelformset\u factory
将其中3个一起渲染。当我在模板上渲染时,一切正常,如下所示

from django import forms
from mailservice.models import categoryprob,Kategori 

PASS_PROB = 0.8

class predictionForm(forms.ModelForm):
    
    class Meta:
        model = Kategori
        fields = ["urun","kategori","ust_kategori","urun_adi","marka","cesidi","miktar","birim","adet"]
        
        widgets = {
            'kategori': forms.Select(choices=set(Kategori.objects.all().values_list('kategori','kategori'))),
            'ust_kategori': forms.Select(choices=set(Kategori.objects.all().values_list('ust_kategori','ust_kategori'))),
            'marka': forms.Select(choices=set(Kategori.objects.all().values_list('marka','marka'))),
            'cesidi': forms.Select(choices=set(Kategori.objects.all().values_list('cesidi','cesidi'))),
            'miktar': forms.Select(choices=set(Kategori.objects.all().values_list('miktar','miktar'))),
            'birim': forms.Select(choices=set(Kategori.objects.all().values_list('birim','birim'))),
            'adet': forms.Select(choices=set(Kategori.objects.all().values_list('adet','adet'))),
        }
        
        labels ={
            'urun':""
        }

    def __init__(self, *args, **kwargs):
        super(predictionForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        prob = categoryprob.objects.get(urun=instance)

        self.fields['urun'].widget.attrs['readonly'] = True

        if float(prob.kategori) > PASS_PROB:
            self.fields['kategori'].widget.attrs['disabled'] = True
            self.fields['kategori'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['kategori'].widget.attrs['style'] = 'border-color:green'

        if float(prob.ust_kategori) > PASS_PROB:
            self.fields['ust_kategori'].widget.attrs['disabled'] = True
            self.fields['ust_kategori'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['ust_kategori'].widget.attrs['style'] = 'border-color:green'
        
        if float(prob.urun_adi) > PASS_PROB:
            self.fields['urun_adi'].widget.attrs['disabled'] = True
            self.fields['urun_adi'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['urun_adi'].widget.attrs['style'] = 'border-color:green'
        
        if float(prob.marka) > PASS_PROB:
            self.fields['marka'].widget.attrs['disabled'] = True
            self.fields['marka'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['marka'].widget.attrs['style'] = 'border-color:green'
        
        if float(prob.cesidi) > PASS_PROB:
            self.fields['cesidi'].widget.attrs['disabled'] = True
            self.fields['cesidi'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['cesidi'].widget.attrs['style'] = 'border-color:green'

        if float(prob.miktar) > PASS_PROB:
            self.fields['miktar'].widget.attrs['disabled'] = True
            self.fields['miktar'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['miktar'].widget.attrs['style'] = 'border-color:green'
        
        if float(prob.birim) > PASS_PROB:
            self.fields['birim'].widget.attrs['disabled'] = True
            self.fields['birim'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['birim'].widget.attrs['style'] = 'border-color:green'
        
        if float(prob.adet) > PASS_PROB:
            self.fields['adet'].widget.attrs['disabled'] = True
            self.fields['adet'].widget.attrs['style'] = 'border-color:red'
        else:
            self.fields['adet'].widget.attrs['style'] = 'border-color:green'


<form method="post" enctype="multipart/form-data">
    
    <div class="form-row">
        {{ p_form.management_form }}
        {% csrf_token %}
        {%for form in p_form%}
        <div class="form-group col-md-12">
            <div class="card">
                <div class="card-header">
                    {{form.urun|as_crispy_field}}
                </div>
                <div class="card-body">
                    
                    <div class="row">   
                        <div class ="col-md-3 col ">
                            {{form.kategori|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.ust_kategori|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.urun_adi|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.marka|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.cesidi|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.miktar|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.birim|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.adet|as_crispy_field}}
                        </div>
                        
                    </div>
                    
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
    
    <button type="submit" class="btn btn-success">Kaydet</button>
</form>
formset.is_始终有效并返回false

我不知道如何一次验证所有表单。你有什么建议吗

模板输出图片:

request.POST的输出:

<QueryDict: {'form-TOTAL_FORMS': ['3'], 'form-INITIAL_FORMS': ['3'], 'form-MIN_NUM_FORMS': ['0'], 'form-MAX_NUM_FORMS': ['1000'], 'csrfmiddlewaretoken': ['*****'], 'form-0-id': ['125'], 'form-0-urun': ['_MotorinEcoForce'], 'form-0-urun_adi': ['asdasd'], 'form-1-id': ['186'], 'form-1-urun': ['7 stick sakız karpuz aromalı 12 adet'], 'form-1-marka': ['7 days'], 'form-2-id': ['159'], 'form-2-urun': ['7 Days Kruvasan Kayısılı Tekli 72 g'], 'form-2-kategori': ['Sebze']}>

可以说有两种形式:绑定形式和未绑定形式。这两者有什么区别?绑定表单被传递一些数据
MyForm(request.POST,request.FILES)
,而未绑定表单没有被传递任何数据
MyForm()
。从逻辑上讲,一个未绑定的表单永远都是无效的,因为它是从未提交的,并且它被认为是为了简单地显示/呈现表单而创建的

这种逻辑同样适用于表单集,因此,由于您没有向表单集传递任何数据,因此它将永远无效。需要考虑的另一件事是,尚未呈现表单集的隐藏字段。表单集生成某些隐藏字段,以便它可以识别哪个子表单是用于哪个对象的,以及一些其他事情,如删除等。没有这些隐藏字段,表单集也将无效

因此,您的观点应该是:

def editCategories(request):
    categories = Kategori.objects.all().order_by('?')[:3]
    CategoryFormSet = modelformset_factory(Kategori, form = predictionForm,extra=0)
    formset = CategoryFormSet(queryset = categories)

    if request.method == "POST":
        # Will get inefficient later on when you have many objects in the database, look for a different solution
        formset = CategoryFormSet(request.POST, request.FILES) # Make a bound formset in case of a POST request
        if formset.is_valid():
            formset.save()
        return redirect(request.META['HTTP_REFERER'])
    content = {
        "p_form":formset,
    }
    return render(request,'edit_categories.html',content)
<form method="post" enctype="multipart/form-data">
    
    <div class="form-row">
        {{ p_form.management_form }}
        {% csrf_token %}
        {%for form in p_form%}
            {# Render hidden fields #}
            {% for hidden in form.hidden_fields %}
                {{ hidden }}
            {% endfor %}
        <div class="form-group col-md-12">
            <div class="card">
                <div class="card-header">
                    {{form.urun|as_crispy_field}}
                </div>
                <div class="card-body">
                    
                    <div class="row">   
                        <div class ="col-md-3 col ">
                            {{form.kategori|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.ust_kategori|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.urun_adi|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.marka|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.cesidi|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.miktar|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.birim|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.adet|as_crispy_field}}
                        </div>
                        
                    </div>
                    
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
    
    <button type="submit" class="btn btn-success">Kaydet</button>
</form>
您的模板应该如下所示:

def editCategories(request):
    categories = Kategori.objects.all().order_by('?')[:3]
    CategoryFormSet = modelformset_factory(Kategori, form = predictionForm,extra=0)
    formset = CategoryFormSet(queryset = categories)

    if request.method == "POST":
        # Will get inefficient later on when you have many objects in the database, look for a different solution
        formset = CategoryFormSet(request.POST, request.FILES) # Make a bound formset in case of a POST request
        if formset.is_valid():
            formset.save()
        return redirect(request.META['HTTP_REFERER'])
    content = {
        "p_form":formset,
    }
    return render(request,'edit_categories.html',content)
<form method="post" enctype="multipart/form-data">
    
    <div class="form-row">
        {{ p_form.management_form }}
        {% csrf_token %}
        {%for form in p_form%}
            {# Render hidden fields #}
            {% for hidden in form.hidden_fields %}
                {{ hidden }}
            {% endfor %}
        <div class="form-group col-md-12">
            <div class="card">
                <div class="card-header">
                    {{form.urun|as_crispy_field}}
                </div>
                <div class="card-body">
                    
                    <div class="row">   
                        <div class ="col-md-3 col ">
                            {{form.kategori|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.ust_kategori|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.urun_adi|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.marka|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.cesidi|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.miktar|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.birim|as_crispy_field}}
                        </div>
                        <div class ="col-md-3 col">
                            {{form.adet|as_crispy_field}}
                        </div>
                        
                    </div>
                    
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
    
    <button type="submit" class="btn btn-success">Kaydet</button>
</form>

您尚未将任何数据传递给表单集,它将如何有效?…我将在editCategories视图
CategoryFormSet(queryset=categories)
中传递数据。感谢您的回答。现在它给了我另一个错误
categoryprob匹配查询不存在。
。当我在
predictionForm
\uuuu init\uuuu
上打印实例时,它会像这样打印
Kategori对象(无)
,然后给出错误。因此,在验证过程中,没有对象返回到表单。@MuratDemir wait您将此作为您的查询集
Kategori.objects.all().order_by('?')[:3]
the
.order_by('?')
表示随机排序,这意味着POST数据中可能存在除作为queryset传递的对象之外的对象,因此您没有与表单集匹配的数据。为什么要这样做?@MuratDemir尝试编写
formset=CategoryFormSet(request.POST,request.FILES)
而不是
formset=CategoryFormSet(request.POST,request.FILES,queryset=categories)
如果是POST请求,这可能会起作用,但会导致从数据库中获取模型的所有实例,如果要为随机排序的查询集创建表单集,您可能需要对获取查询集的方式进行一些调整。@MuratDemir这可能是因为您只是向其小部件添加了一个禁用的属性,而不是禁用该字段,因此它不会被发布(这很好)但该字段随后认为这意味着将该值设置为null。而不是
self.fields['ustu kategori'].widget.attrs['disabled']=True
等。你想写
self.fields['ustu kategori'].disabled=True
Omg,你是个天才。非常感谢,它工作得很好。我终于完成了任务,你救了我一天。