【问题标题】:Can a django formset that dynamically adds fields have persistent data?动态添加字段的 django formset 可以具有持久数据吗?
【发布时间】:2013-08-02 12:32:27
【问题描述】:

我正在 python/django 中创建一个表单集,并且需要在单击按钮时向表单集动态添加更多字段。我正在处理的表格是针对我的学校询问学生他们想向谁披露某些学术信息的,这里的按钮允许他们添加更多字段以输入他们想向其披露的家庭成员/人。

我的按钮工作到显示额外字段的位置,您可以添加任意数量的字段。问题是,之前输入到现有字段中的数据被删除了。但是,只有表单集中的内容会被删除。之前在表单中填写的所有其他内容都将保持不变。

有什么方法可以让表单集保留按下按钮之前输入的数据?

form.py:

from django import forms
from models import Form, ParentForm, Contact
from django.core.exceptions import ValidationError

def fff (value):
    if value == "":
        raise ValidationError(message = 'Must choose a relation', code="a")

# Create your forms here.
class ModelForm(forms.ModelForm):   
    class Meta:
        model = Form
        exclude = ('name', 'Relation',)

class Parent(forms.Form):
    name = forms.CharField()

    CHOICES3 = (    
    ("", '-------'),
    ("MOM", 'Mother'),
    ("DAD", 'Father'),
    ("GRAN", 'Grandparent'),
    ("BRO", 'Brother'),
    ("SIS", 'Sister'),
    ("AUNT", 'Aunt'),
    ("UNC", 'Uncle'),
    ("HUSB", 'Husband'),
    ("FRIE", 'Friend'),
    ("OTHE", 'Other'),
    ("STEP", 'Stepparent'),
    )
    Relation = forms.ChoiceField(required = False, widget = forms.Select, choices = CHOICES3, validators = [fff])

models.py

from django.db import models
from django import forms
from content.validation import *
from django.forms.models import modelformset_factory

class Contact(models.Model):
    name = models.CharField(max_length=100)

class Form(models.Model):
    CHOICES1 = (
        ("ACCEPT", 'I agree with the previous statement.'),
        )
    CHOICES2 = (
        ("ACADEMIC", 'Academic Records'),
        ("FINANCIAL", 'Financial Records'),
        ("BOTH", 'I would like to share both'),
        ("NEITHER", 'I would like to share neither'),
        ("OLD", "I would like to keep my old sharing settings"),
        )

    Please_accept = models.CharField(choices=CHOICES1, max_length=200)
    Which_information_would_you_like_to_share = models.CharField(choices=CHOICES2, max_length=2000)
    Full_Name_of_Student = models.CharField(max_length=100)
    Carthage_ID_Number = models.IntegerField(max_length=7)
    I_agree_the_above_information_is_correct_and_valid = models.BooleanField(validators=[validate_boolean])
    Date = models.DateField(auto_now_add=True)
    name = models.ManyToManyField(Contact, through="ParentForm")

class ParentForm(models.Model):
    student_name = models.ForeignKey(Form)
    name = models.ForeignKey(Contact)

    CHOICES3 = (
    ("MOM", 'Mother'),
    ("DAD", 'Father'),
    ("GRAN", 'Grandparent'),
    ("BRO", 'Brother'),
    ("SIS", 'Sister'),
    ("AUNT", 'Aunt'),
    ("UNC", 'Uncle'),
    ("HUSB", 'Husband'),
    ("FRIE", 'Friend'),
    ("OTHE", 'Other'),
    ("STEP", 'Stepparent'),
    )
    Relation = models.CharField(choices=CHOICES3, max_length=200)
    def __unicode__(self):
        return 'name: %r, student_name: %r' % (self.name, self.student_name)

和views.py

from django.shortcuts import render
from django.http import HttpResponse
from form import ModelForm, Parent
from models import Form, ParentForm, Contact
from django.http import HttpResponseRedirect
from django.forms.formsets import formset_factory

def create(request):
    ParentFormSet = formset_factory(Parent, extra=1)
    if request.POST:        
        Parent_formset = ParentFormSet(request.POST, prefix='Parent_or_Third_Party_Name')
        if 'add' in request.POST:
            list=[]
            for kitties in Parent_formset:
                list.append({'Parent_or_Third_Party_Name-0n-ame': kitties.data['Parent_or_Third_Party_Name-0-name'], 'Parent_or_Third_Party_Name-0-Relation': kitties.data['Parent_or_Third_Party_Name-0-Relation']})
            Parent_formset = ParentFormSet(prefix='Parent_or_Third_Party_Name', initial= list)
        form = ModelForm(request.POST)
        if form.is_valid() and Parent_formset.is_valid():
            form_instance = form.save()

            for f in Parent_formset:
                if f.clean():
                    (obj, created) = ParentForm.objects.get_or_create(name=f.cleaned_data['name'], Relation=f.cleaned_data['Relation'])

            return HttpResponseRedirect('http://Google.com')
    else:
        form = ModelForm()
        Parent_formset = ParentFormSet(prefix='Parent_or_Third_Party_Name')

    return render(request, 'content/design.html', {'form': form, 'Parent_formset': Parent_formset})
def submitted(request):
    return render(request, 'content/design.html')

提前谢谢你!

【问题讨论】:

    标签: python database django django-forms


    【解决方案1】:

    我之前在 Django 中动态添加字段时遇到了麻烦,这个 stackoverflow 问题帮助了我: dynamically add field to a form

    老实说,在您的情况下,我不完全确定您所说的“持久”是什么意思 - 在您添加输入时,表单的值是否会被删除?你确定这不是你的 JS 的问题吗?

    【讨论】:

    • 另外,对风格的友好评论:您可能希望将模型中的所有字段都设为小写_下划线。您在大写和大写之间切换(例如,您的表单模型的“名称”和“日期”)
    • 正在删除表单集中的值。当然,现在我开始赏金了,我的一位同事帮我解决了这个问题
    • 刚刚意识到我从来没有接受过你的回答。很抱歉!
    【解决方案2】:

    我的一位同事终于想通了。这是修改后的views.py:

    from django.shortcuts import render
    from django.http import HttpResponse
    from form import ModelForm, Parent
    from models import Form, ParentForm, Contact
    from django.http import HttpResponseRedirect
    from django.forms.formsets import formset_factory
    
    def create(request):
        ParentFormSet = formset_factory(Parent, extra=1)
        boolean = False
        if request.POST:        
            Parent_formset = ParentFormSet(request.POST, prefix='Parent_or_Third_Party_Name')
            if 'add' in request.POST:
                boolean = True
                list=[]
                for i in range(0,int(Parent_formset.data['Parent_or_Third_Party_Name-TOTAL_FORMS'])):
                    list.append({'name': Parent_formset.data['Parent_or_Third_Party_Name-%s-name' % (i)], 'Relation': Parent_formset.data['Parent_or_Third_Party_Name-%s-Relation' % (i)]})
                Parent_formset = ParentFormSet(prefix='Parent_or_Third_Party_Name', initial= list)
            form = ModelForm(request.POST)
            if form.is_valid() and Parent_formset.is_valid():
                form_instance = form.save()                 
    
                for f in Parent_formset:
                    if f.clean():
                        (contobj, created) = Contact.objects.get_or_create(name=f.cleaned_data['name'])
                        (obj, created) = ParentForm.objects.get_or_create(student_name=form_instance, name=contobj, Relation=f.cleaned_data['Relation'])
    
                return HttpResponseRedirect('http://Google.com')
        else:
            form = ModelForm()
            Parent_formset = ParentFormSet(prefix='Parent_or_Third_Party_Name')
    
        return render(request, 'content/design.html', {'form': form, 'Parent_formset': Parent_formset, 'boolean':boolean})
    def submitted(request):
        return render(request, 'content/design.html')
    

    感谢您的意见,那些回答的人:)

    【讨论】:

      【解决方案3】:

      我曾经试图做这样的事情,但被一个比我聪明得多的人引导到django-crispy-forms。我从未完成过这个项目,所以我无法提供更多帮助,但这可能是一个开始点。

      【讨论】:

      • 如果我决定朝那个方向发展,那将是一个很好的起点,但形式已经非常成熟,缺少的只是坚持......我希望会有一些我可以直接实现,而不是重写整个表单
      • 希望我能提供更多帮助。我会自己看这个问题,因为我从来没有超过这一点。
      • 投个赞成票和收藏,让我们拭目以待吧!
      【解决方案4】:

      如果您的表单集没有显示您之前所做的输入,则意味着它看不到模型的查询集。将查询集添加到表单集参数以解决此问题。例如:

      formset = SomeModelFormset(queryset=SomeModel.objects.filter(arg_x=x))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-17
        • 2020-07-22
        • 2019-11-27
        • 1970-01-01
        • 2017-04-23
        • 2019-12-02
        • 2015-11-18
        • 1970-01-01
        相关资源
        最近更新 更多