首页 文章

如何为Django ModelForm创建子表单

提问于
浏览
1

我在使用ModelForm添加ManyToMany字段时遇到问题,问题是我不知道如何创建子表单以将此数据添加到我的主表单 . 我想在单击按钮时创建要保存的子表单,并且我希望选择保存的数据以在主表单中使用 .

我的模特

class Teste(models.Model):

   name = models.CharField(max_length=255)
   parent_institution_name = models.CharField(max_length=255)
   laboratory_departament = models.CharField(max_length=255, null=True, 
   blank=True, verbose_name="Laboratório")
   cep = models.CharField(max_length=255, verbose_name="Cep")
   cnpj = models.CharField(max_length=255, verbose_name="CNPJ")
   lat = models.FloatField(blank=True, null=True)
   lng = models.FloatField(blank=True, null=True)
   institution_name = models.CharField(max_length=255, null=False, 
   verbose_name="Nome da instituição")
   parent_institution_name = models.CharField(max_length=255, blank=True, 
   null=True, verbose_name="Nome da instituição vinculada")
   coordinator = models.CharField(max_length=255, verbose_name="Pessoa 
   Responsavel")
   email = models.CharField(max_length=255, verbose_name="E-mail")
   website = models.CharField(max_length=255, blank=True, null=True, 
   verbose_name="Website")
   rad_operating_time = models.IntegerField(verbose_name="Tempo de atuação 
   ")
   research_line = models.ManyToManyField('researcher.ResearchLines')

我的ModelForm类TestForm(forms.ModelForm):类Meta:

model = Test
        exclude = ('employee_number', ' revenues', 'filter_grade', 'grade', ' 
        knowledge_grade',
    'application_grade', 'ie_grade', ' ia_grade', 'final_grade', 'inactive', 'last_coordinator_access', ' hr_count',
    'hr_returned', ' match_hr_count', 'general_grade', 'lat', 'lng'
    'tokens', 'iso_certification', 'other_certification', 'researchers', 'thematic_network',
    )


    widgets ={
        'name':forms.TextInput(attrs={
            'class':'form-control',
            'placeholder': 'Nome da UBC'
        }),
        'parent_institution_name': forms.TextInput(attrs={
            'class':'form-control',
            'placeholder':'Nome da Instituição à qual a UBC é vinculada'
        }),
        'laboratory_departament': forms.TextInput(attrs={
            'class':'form-control',
            'placeholder':'Laboratório/Departamento'
        }),
        'cep': forms.TextInput(attrs={
            'class':'form-control',
            'placeholder':'CEP'
        }),
        'cnpj': forms.TextInput(attrs={
            'class':'form-control',
            'placeholder':'CNPJ'
        }),
        'institution_name': forms.TextInput(attrs={
            'class':'form-control',
            'placeholder':'Nome da instituição'
        }),
        'coordinator': forms.TextInput(attrs={
            'class':'form-control',
            'placeholder':'Pessoa Responsável'

        }),
        'email': forms.TextInput(attrs={
            'class':'form-control',
            'placeholder':'E-mail'
        }),
        'website': forms.TextInput(attrs={
            'class':'form-control',
            'placeholder':'Website'
        }),
        'rad_operating_time': forms.TextInput(attrs={
            'class':'form-control',
            'placeholder':'Tempo de atuação em projetos de P&D+I'
        }),
        'phone': forms.TextInput(attrs={
            'class':'form-control',
            'placeholder': 'Telefone'
        }),
        'partner_category': forms.RadioSelect(),

        'main_product':forms.CheckboxSelectMultiple( attrs={
            'type':'checkbox'
        }),        
    }

我的表单看起来如何,最后一个输入显示子表单添加数据的位置

enter image description here

2 回答

  • 0

    Jaberwocky这是我的代码,我必须提前告诉我仍在学习的代码

    class Ubc(models.Model):
        """ Table Ubc """
        name = models.CharField(verbose_name="Nome da instituição", max_length=255, null=False)
        laboratory_departament = models.CharField(max_length=255, null=True, blank=True, verbose_name="Laboratório")
        cep = models.CharField(max_length=255, verbose_name="Cep", null=True)
        cnpj = models.CharField(max_length=255, verbose_name="CNPJ", null=True)
        lat = models.FloatField(blank=True, null=True)
        lng = models.FloatField(blank=True, null=True)
        street = models.CharField(max_length=255, verbose_name="Endereco", null=True, blank=True)
        uf = models.CharField(max_length=255, verbose_name="UF", null=True, blank=True)
        city = models.CharField(max_length=255, verbose_name="City", null=True, blank=True)
        parent_institution_name = models.CharField(verbose_name="Nome da instituição vinculada", max_length=255, blank=True, null=True)
        coordinator = models.CharField(max_length=255, verbose_name="Pessoa Responsavel")
        email = models.CharField(max_length=255, verbose_name="E-mail")
        website = models.CharField(max_length=255, blank=True, null=True, verbose_name="Website")
        rad_operating_time = models.IntegerField(verbose_name="Tempo de atuação em projetos de P&D+I")
    
        phone = models.CharField(max_length=255, verbose_name="Telefone", null=True)
        inactive = models.NullBooleanField(verbose_name="Inativo", default=False, null=True)
        partner_category = models.ForeignKey('PartnerSubCategory', on_delete=models.CASCADE)
        parent = models.ForeignKey('Company', blank=True, null=True, on_delete=models.CASCADE)
        general_grade = models.ForeignKey('GeneralGrade', blank=True, null=True, on_delete=models.CASCADE)
        main_product = models.ManyToManyField('MainProductUbc', verbose_name="Qual o tipo de produto e/ou servico que a UBC fornece (produto, processo, mudanca organizacional)")
        tokens = models.ManyToManyField('ubc.Token', blank=True, related_name='tokens')
        activity_branch = models.ForeignKey('ActivityBranch', verbose_name="Ramo de Atividade (CNAE)", null=True, on_delete=models.CASCADE)      
        researchers = models.ManyToManyField('researcher.Researcher', related_name='researchers', through='researcher.ResearcherUbc', blank=True)    
        research_line = models.ManyToManyField('researcher.ResearchLines',related_name='ubc_lines', blank=True)  
    
    
    class ResearchLines(models.Model):
        title = models.CharField(verbose_name="Descrição da Linha de Pesquisa", max_length=255, blank=True, null=True)
        ubc = models.ForeignKey('ubc.Ubc', on_delete=models.CASCADE)
        created = models.DateTimeField(auto_now_add=True)
        updtaed = models.DateTimeField(auto_now=True)
    
        class Meta:
            verbose_name_plural = 'Research Line'
    
        def __str__(self):
            return self.title
    

    views.py

    def ubc_register(request):
        if request.method == "POST":
            form = UbcForm(request.POST or None)
            if form.is_valid():
                form = form.save(commit=False)
                formset = LinesFormSet(request.POST, request.FILES, instance=form)
                if formset.is_valid():
                    form.save()
                    formset.save()         
                return HttpResponseRedirect(reverse('index'))
        else:
            form = UbcForm(prefix="form")
            formset = LinesFormSet(prefix="formset")
            context = {
                'form':form,
                'formset':formset
            }
            return render(request, 'accounts/ubc_form.html', context)
    

    forms.py

    class UbcForm(forms.ModelForm):
    
    
        class Meta:
    
            research_line = forms.ModelMultipleChoiceField(queryset=ResearchLines.objects.all())
    
            model = Ubc
            exclude = ('employee_number', ' revenues', 'filter_grade', 'grade', 
            ' knowledge_grade',
            'application_grade', 'ie_grade', ' ia_grade', 'final_grade', 
            'inactive', 'last_coordinator_access', ' hr_count',
            'hr_returned', ' match_hr_count', 'general_grade', 'lat', 'lng'
            'tokens', 'iso_certification', 'other_certification', 'researchers', 
            'thematic_network',
         )
    
    
            widgets ={
                'name':forms.TextInput(attrs={
                'class':'form-control',
                'placeholder': 'Nome da UBC'
            }),
                'parent_institution_name': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'Nome da Instituição à qual a UBC é vinculada'
            }),
                'laboratory_departament': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'Laboratório/Departamento'
            }),            
                'cnpj': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'CNPJ'
            }),
                'institution_name': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'Nome da instituição'
            }),
                'coordinator': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'Pessoa Responsável'
    
            }),
                'email': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'E-mail'
            }),
                'website': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'Website'
            }),
                'rad_operating_time': forms.NumberInput(attrs={
                'class':'form-control',
                'placeholder':'Tempo de atuação em projetos de P&D+I'
            }),
                'phone': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder': 'Telefone'
            }),
                'partner_category': forms.RadioSelect(),
    
                'main_product':forms.CheckboxSelectMultiple( attrs={
                'type':'checkbox'
            }),   
                'activity_branch':forms.Select( attrs={
                'class':'form-control'
            }),
                'research_line':forms.TextInput(attrs={
                'class':'form-control'
            }),
    
                'cep': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'CEP'
            }),
                'street': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'Endereço'
            }),
                'city': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'Cidade'
            }),
                'uf': forms.TextInput(attrs={
                'class':'form-control',
                'placeholder':'UF'
            }),
    
    
        }
    
    class ResearchLineForm(forms.ModelForm):
        class Meta:
            model = ResearchLines
            fields = ('title', )
    
            widgets = {
                'title':forms.TextInput(attrs={
                'class':'form-control'
            })
        }
    
    class AddressForm(forms.ModelForm):
        model = Address
        fields = '__all__'
    
    
    LinesFormSet = inlineformset_factory(
        Ubc,
        ResearchLines,
        fields=('title', ),
        extra=1,
        widgets = {
            'title':forms.TextInput(attrs={
                'class':'form-control'
        })
    }
    )
    

    在我的form.html里面的formset标签和来自django-dynamic-formset的脚本来生成新表单

    {{formset.management_form}}
    {% for form in formset %}                
         <div class="link-formset">
             {{ form }}                                                           
         </div>
     {% endfor %}
    
    
    <script>
        $('.link-formset').formset({
            addText: 'add link',
            deleteText: 'remove'
        });
    </script>
    
  • 2

    这是一个我使用内联表单集的示例,它实际上将两个表单组合成一个显示的表单 . formset是服务形式,并且打孔形成我的意图是拳头是“形式中的形式” .

    enter image description here

    VIEWS.PY (the most influential part)

    def reportcreateview(request):
        if request.method == 'POST':
            reportform = ServiceReportCreateForm(request.POST)
            if reportform.is_valid():
                report = reportform.save(commit=False)
                report.reported_by = request.user
                punchesform = PunchesFormSet(request.POST, request.FILES, instance=report)
                if punchesform.is_valid():
                    report.save()
                    punchesform.save()
                return redirect('service:update-report', pk=report.pk)
        else:
            punchesform = PunchesFormSet()
            reportform = ServiceReportCreateForm()
            reportform.reported_by = request.user
        context = {
            'report': reportform,
            'punches': punchesform,
        }
        return render(request, 'service/report-create.html', context)
    

    FORMS.PY

    from django import forms
    from django.forms.models import inlineformset_factory, BaseInlineFormSet
    from .models import ServiceReportModel, ReportPunchesModel, ServiceRequestModel
    
    
    class ServiceReportCreateForm(forms.ModelForm):
    
        class Meta:
            model = ServiceReportModel
            fields = [
                'site',
                'invoiced',
                'paid',
                'request_number',
                'equipment',
                'report_reason',
                'actions_taken',
                'recommendations',
            ]
            widgets = {
                'site': forms.Select(attrs={
                    'class': 'form-control',
                    'id': 'inputSite',
                }),
                'invoiced': forms.CheckboxInput(attrs={
                    'class': 'form-control',
                }),
                'paid': forms.CheckboxInput(attrs={
                    'class': 'form-control',
                }),
                'request_number': forms.Select(attrs={
                    'class': 'form-control',
                    'id': 'inputRequest',
                }),
                'equipment': forms.Select(attrs={
                    'class': 'form-control',
                    'id': 'inputEquipment',
                }),
                'report_reason': forms.TextInput(attrs={
                    'class': 'form-control',
                    'placeholder': 'Enter Reason for Service Report'}),
                'actions_taken': forms.Textarea(attrs={
                    'class': 'form-control',
                    'placeholder': 'To the best of your abilities, list all actions taken during service.  Please include'
                    'dates, times, and equipment names'}),
                'recommendations': forms.Textarea(attrs={
                    'class': 'form-control',
                    'placeholder': 'If any recommendations were made to the customer that'
                                   'require follow-up itemize them here...'}),
            }
    
            def __init__(self, *args, **kwargs):
                super(ServiceReportCreateForm, self).__init__(*args, **kwargs)
                self.fields['request_number'].required = False
    
    
    class ServiceReportUpdateForm(forms.ModelForm):
    
        def __init__(self, *args, **kwargs):
            super(ServiceReportUpdateForm, self).__init__(*args, **kwargs)
            instance = getattr(self, 'instance', None)
            if instance and instance.pk:
                self.fields['request_number'].required = False
                self.fields['report_reason'].widget.attrs['readonly'] = True
    
        class Meta:
            model = ServiceReportModel
            fields = [
                'invoiced',
                'paid',
                'request_number',
                'updated_by',
                'report_reason',
                'actions_taken',
                'recommendations',
            ]
            widgets = {
                'invoiced': forms.CheckboxInput(attrs={
                    'class': 'form-control',
                }),
                'paid': forms.CheckboxInput(attrs={
                    'class': 'form-control',
                }),
                'request_number': forms.Select(attrs={
                    'class': 'form-control',
                    'id': 'inputRequest',
                }),
                'updated_by': forms.Select(attrs={
                    'class': 'form-control',
                    'id': 'inputReporter',
                }),
                'report_reason': forms.TextInput(attrs={
                    'class': 'form-control',
                    'placeholder': 'Enter Reason for Service Report'}),
                'actions_taken': forms.Textarea(attrs={
                    'class': 'form-control',
                    'placeholder': 'To the best of your abilities, list all actions taken during service.  Please include' +
                    'dates, times, and equipment names'}),
                'recommendations': forms.Textarea(attrs={
                    'class': 'form-control',
                    'placeholder': 'If any recommendations were made to the customer that'
                                   'require follow-up itemize them here...'}),
            }
    
    
    PunchesFormSet = inlineformset_factory(
        ServiceReportModel,
        ReportPunchesModel,
        fields=('date',
                'time_in',
                'time_out',
                ),
        widgets={
                'date': forms.DateInput(attrs={
                    'type': 'date'
                }),
                'time_in': forms.TimeInput(attrs={
                    'type': 'time'
                }),
                'time_out': forms.TimeInput(attrs={
                    'type': 'time'
                })},
        extra=1,
        can_order=True
    )
    

    MODELS.PY

    class ServiceReportModel(ServiceParent):
        report_number = models.UUIDField(
            primary_key=True, default=uuid.uuid4, editable=False)
        invoiced = models.BooleanField(default=False, null=False)
        paid = models.BooleanField(default=False, null=False)
        request_number = models.ForeignKey(ServiceRequestModel,
                                           on_delete=models.PROTECT,
                                           null=True,
                                           blank=True,
                                           related_name='s_report_number'
                                           )
        reported_by = models.ForeignKey(
            main_models.MyUser, related_name='reporter', on_delete=models.PROTECT)
        reported_date = models.DateTimeField(auto_now_add=True)
        report_reason = models.CharField(max_length=255, null=True)
        actions_taken = models.TextField(null=False, blank=False)
        recommendations = models.TextField(null=True, blank=True)
    
        def get_absolute_url(self):
            return reverse('service-report', kwargs={'pk': self.pk})
    
        def __str__(self):
            return '%s - %s, %s' % (self.site.company,
                                    self.reported_date.strftime('%d %B %Y'),
                                    self.equipment.name
                                    )
    
        class Meta:
            ordering = ['reported_date', 'updated_date']
            verbose_name = 'Service Report'
            verbose_name_plural = 'Service Reports'
    
    
    class ReportPunchesModel(models.Model):
        punch_id = models.UUIDField(
            primary_key=True, default=uuid.uuid4, editable=False)
        added = models.DateTimeField(auto_now_add=True)
        report = models.ForeignKey(ServiceReportModel, on_delete=models.CASCADE)
        date = models.DateField(blank=True, null=True)
        time_in = models.TimeField(blank=True, null=True)
        time_out = models.TimeField(blank=True, null=True)
    
        def __str__(self):
            return '%s - %s' % (self.time_in,
                                self.time_out
                                )
    
        class Meta:
            ordering = ['added', 'date', 'time_in']
            verbose_name = 'Report Punches'
            verbose_name_plural = verbose_name
    

相关问题