簡體   English   中英

如何將不同的 model 表單添加到 modelformset_factory

[英]how to add a different model form to modelformset_factory

關於這些模型:

class Projects(models.Model):
    projectDescription = models.CharField(max_length=50,blank=True,null = True,)
    status = models.IntegerField(choices = Status_CHOICES, default = 4)
    projectOwner = models.ForeignKey(staff, on_delete=models.CASCADE, blank=True,null = True,)

class Updates(models.Model):
    project = models.ForeignKey(Projects, on_delete=models.CASCADE)
    update = models.CharField(max_length=50,blank=True,null = True,)
    updateDate = models.DateTimeField(default = timezone.now, editable = False)
    addedBy = models.CharField(max_length=35,blank=True,)

我想為所有當前項目創建一個顯示 forms 的視圖。 這很容易使用modelformset_factory 但是,我怎樣才能向這些項目表單實例中的每一個添加一個額外的表單,以便可以對項目(外鍵)進行更新 理想情況下,用戶對各種項目進行更改,為一個或多個項目添加更新,然后提交表單以保存所有更改。 我在下面的內容似乎非常接近,但它正在保存每個項目的更新,其中包含我在最后一個表單中輸入的任何內容的值。 這似乎是因為形式不是唯一的。 我走上了使用前綴的道路,這似乎也沒有讓我到任何地方。 幫助!

更新表格

class updateForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(updateForm, self).__init__(*args, **kwargs)
    class Meta:
        model = Updates
        fields = ('update',)

看法:

def MDSprojects(request):
    projects = Projects.objects.filter(dept = 'Assistive Technology')
    projectFormset = modelformset_factory(Projects, form=EditProjectForm, extra = 0)

    if request.method == 'POST':
        formsetA = projectFormset(request.POST,request.FILES)
        if formsetA.is_valid():
            for f in formsetA:
                formA = f.save(commit = False)
                id = formA.id
                formA.save()
                formsetB = updateForm(request.POST,request.FILES)
                if formsetB.is_valid():
                    formB = formsetB.save(commit = False)
                    project = Projects.objects.get(id = id)
                    formB.project = project
                    formB.save()
                else:
                    print(formsetB.errors)
            return redirect('MDS_Projects')
        else:
            print(formsetA.errors)
    else:
        formsetA = projectFormset(queryset = projects)
        formsetB = updateForm()
        return render(request,'MDSprojectsB.html',{'formset':formsetA,'formsetB':formsetB,})

模板:

<form method="POST" enctype= multipart/form-data>
  {{ formset.management_form }}
  {% csrf_token %}
  {%for form in formset%}
    {{ form.management_form }}
    {% for hidden in form.hidden_fields %}
      {{ hidden }}
    {% endfor %}
  <div class="card border-primary mb-3" style="max-width: 85rem;">
    <div class="card-header text-primary">
       <strong>{{form.instance.projectDescription}}</strong>
    </div>
    <div class="card-body text-primary"> Project Name: {{form.projectDescription}}</div>
    <div class="card-body text-primary"> Status: {{form.status}}</div>
    <div class="card-body text-primary"> Status: {{form.projectOwner}}</div>
    <div class="card-body text-primary"> Status: {{form.priority}}</div>
    <div>
        {{ formsetB.management_form }}
        {% for hidden in formsetB.hidden_fields %}
          {{ hidden }}
        {% endfor %}
        {{formsetB}}
    </div>
  </div>
  {% endfor %}
  <button class="btn btn-success btn" type="submit">Save Changes</button>
 </form>

編輯:

也許解釋我的問題的另一種方式是:

如果我有與上述相同的模型:

class Projects(models.Model):
    projectDescription = models.CharField(max_length=50,blank=True,null = True,)
    status = models.IntegerField(choices = Status_CHOICES, default = 4)
    projectOwner = models.ForeignKey(staff, on_delete=models.CASCADE, blank=True,null = True,)

class Updates(models.Model):
    project = models.ForeignKey(Projects, on_delete=models.CASCADE)
    update = models.CharField(max_length=50,blank=True,null = True,)
    updateDate = models.DateTimeField(default = timezone.now, editable = False)
    addedBy = models.CharField(max_length=35,blank=True,)

我想要一個視圖,將所有當前項目呈現為單獨的 forms,以便用戶可以在一個視圖中對項目 model 進行更改。 此外,我希望用戶也能夠為每個項目添加更新。

例如,如果我有 3 個項目,我希望在頁面上看到 3 個 forms。 每個表單都將包含修改此項目的字段(因此這些表單字段將預先填充當前值)。 最后(我堅持的部分)將是一個額外的空白字段,用於向項目添加更新。

解決方案一

你所做的幾乎是正確的。 您已經啟動了一個 UpdateForm,但您將它視為一個表單集。 但是它是一個 Form 實例。 如果您按以下方式更改代碼,您可能會實現您的目標。

模型.py

class Project(models.Model):
    description = models.CharField(max_length=50, blank=True, null=True)
    status = models.IntegerField(choices=STATUS_CHOICES, default=4)
    owner = models.ForeignKey(staff, on_delete=models.CASCADE, blank=True, null=True)
    ...

class Update(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    notes = models.CharField(max_length=50, blank=True, null=True)
    update_date = models.DateTimeField(default=timezone.now, editable=False)
    added_by = models.CharField(max_length=35, blank=True)

forms.py

class CreateUpdateForm(ModelForm):
    class Meta:
        model = Update
        fields = ('notes')


class EditProjectForm(ModelForm)
    class Meta:
        model = Project
        fields = ('__all__')

視圖.py

def mds_projects(request):
    project_formset = modelformset_factory(Project, form=EditProjectForm, extra=0)

    if request.method == 'POST':
        formset = project_formset(request.POST,request.FILES)
        if formset.is_valid():
            for f in formset:
                project = f.save(commit = False)

                update_form = CreateUpdateForm(request.POST,request.FILES)
                if update_form.is_valid():
                    update = update_form.save(commit = False)
                    update.project = project
                    project.save()
                    update.save()
                else:
                    print(update_form.errors)
            return redirect('MDS_Projects')
        else:
            print(formset.errors)
    else:
        projects = Project.objects.filter(dept='Assistive Technology')
        formset = project_formset(queryset=projects)
        update_form = updateForm()
        return render(request,'MDSprojectsB.html',{'formset':formset, 'update_form':update_form})

MDS項目B.html

<form method="POST" enctype= multipart/form-data>
  {{ formset.management_form }}
  {% csrf_token %}
  {%for form in formset%}
    {{ form.management_form }}
    {% for hidden in form.hidden_fields %}
      {{ hidden }}
    {% endfor %}
  <div class="card border-primary mb-3" style="max-width: 85rem;">
    <div class="card-header text-primary">
       <strong>{{form.instance.description}}</strong>
    </div>
    <div class="card-body text-primary"> Project Name: {{form.description}}</div>
    <div class="card-body text-primary"> Status: {{form.status}}</div>
    <div class="card-body text-primary"> Owner: {{form.owner}}</div>
    <div class="card-body text-primary"> Priority: {{form.priority}}</div>
    <div>
        {{ update_form }}
    </div>
  </div>
  {% endfor %}
  <button class="btn btn-success btn" type="submit">Save Changes</button>
 </form>

解決方案二

您也可以對兩種模型使用一種形式。 由於您只需要Update model 的更新說明,因此您可以添加額外的表單字段來更新項目表單,因此您不需要額外的更新表單。

forms.py

class EditProjectForm(ModelForm)
    update_notes = forms.CharField(max_length=50, help_text='50 characters max.')
    class Meta:
        model = Project
        fields = ('__all__')

視圖.py

def mds_projects(request):
    project_formset = modelformset_factory(Project, form=EditProjectForm, extra=0)

    if request.method == 'POST':
        formset = project_formset(request.POST,request.FILES)
        if formset.is_valid():
            for f in formset:
                project = f.save(commit = False)
                update = Update.objects.create(notes=f.cleaned_data['update_notes'], project=project)
                project.save()

            return redirect('MDS_Projects')
        else:
            print(formset.errors)
    else:
        projects = Project.objects.filter(dept='Assistive Technology')
        formset = project_formset(queryset=projects)
        return render(request,'MDSprojectsB.html',{'formset':formset})

MDS項目B.html

<form method="POST" enctype= multipart/form-data>
  {{ formset.management_form }}
  {% csrf_token %}
  {%for form in formset%}
    {{ form.management_form }}
    {% for hidden in form.hidden_fields %}
      {{ hidden }}
    {% endfor %}
  <div class="card border-primary mb-3" style="max-width: 85rem;">
    <div class="card-header text-primary">
       <strong>{{form.instance.description}}</strong>
    </div>
    <div class="card-body text-primary"> Project Name: {{form.description}}</div>
    <div class="card-body text-primary"> Status: {{form.status}}</div>
    <div class="card-body text-primary"> Owner: {{form.owner}}</div>
    <div class="card-body text-primary"> Priority: {{form.priority}}</div>
    <div class="card-body text-primary"> Update: {{form.update_notes}}</div>
  </div>
  {% endfor %}
  <button class="btn btn-success btn" type="submit">Save Changes</button>
 </form>

PS您提供的代碼有些違反 python 和 django 命名約定。 請盡量遵守這些約定。 我已經在我的代碼中修復了其中的一些問題。 例如,你不應該為你的模型命名復數,你應該為函數和變量使用駝峰命名法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM