【问题标题】:How to dynamically change a form in django based on user input (before submission)如何根据用户输入动态更改 django 中的表单(提交前)
【发布时间】:2020-12-05 18:36:13
【问题描述】:

我正在做一个网页,其中包含一个必须根据之前的用户输入(在提交之前)动态更改的表单。例如,如果名称以字符串S.L 结尾,则需要自动跨越其余字段以引入公司数据,否则必须使用默认值或任何值提交表单。

表单继承自模型,所有内容都呈现为酥脆的表单。

在 views.py 我有:

@login_required
def form_home(request):

    if request.method == 'POST':

        Inputs = InputsForm(request.POST)

        if Inputs.is_valid():

            inp = Inputs.save(commit=False)
            inp.author = request.user
            inp.email = request.user.email

            data = {'email': request.user.email, **Inputs.cleaned_data}
            obtain_calculate_create_send(data)

            inp.save()
            messages.success(request, f'Your form is valid!')
            return redirect('result/' + str(inp.pk) + '/')
        else:
            messages.warning(request, f'Please, check the inputs and enter valid ones')

        content = {'Inputs': Inputs, 'title': 'valuations'}

    else:
        Inputs = InputsForm(request.POST or None)
        content = {'Inputs': Inputs, 'title': 'valuations'}

    return render(request, 'valuations/form_home.html', content)

在forms.py中:

class InputsForm(forms.ModelForm):
    # Basic Info 

    country_choices = import_lists('Countries', equal=True)
    years = import_lists('years')

    name = forms.CharField(label='Company Name', initial='Example. S.L')
    country = forms.TypedChoiceField(choices=country_choices, label='Country')
    foundation_year = forms.TypedChoiceField(coerce=int, choices=years, label='Foundation year')
    employees = forms.IntegerField(label='Number of employees')
    industry = forms.TypedChoiceField(choices=industry_choices, label='Industry')
    class Meta:
        model = Inputs
        exclude = ('author', 'email', 'date_inputs_created ')

在models.py中:

class Inputs(models.Model):

    def __str__(self):
        return f'{self.author}´s inputs for {self.name} created at {self.date_inputs_created}'

    # Useful information for the data base
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    date_inputs_created = models.DateTimeField(auto_now_add=True)
    email = models.EmailField(max_length=254, default='example@compani.com')

    # Actual inputs
    # Basic Info 
    # ---------
    country_choices = import_lists('Countries', equal=True)
    industry_choices = import_lists('Industry', equal=True)

    name = models.CharField(max_length=100)
    country = models.CharField(max_length=30, choices=country_choices, default='Germany')
    foundation_year = models.PositiveSmallIntegerField(choices=years)
    employees = models.PositiveIntegerField(default=20)
    industry = models.CharField(max_length=50, choices=industry_choices)

在 HTML 中:

{% block content %}
  <form method="post">
    {% csrf_token %}
    {{ Inputs|crispy }}
    <button type="submit" class="btn btn-primary">submit</button>
  </form>
{% endblock %}

感谢任何帮助,提前致谢。

【问题讨论】:

    标签: python html django forms dynamic


    【解决方案1】:

    为了让您了解如何改变它,我认为可以通过三种方式实现。

    1. 使用 Django Signals 运行预保存函数,检查名称是否包含“S.L”并相应地应用字段逻辑。

    2. 更改您的视图功能并在那里应用逻辑。

    3. 劫持您的模型保存方法并检查名称是否包含“S.L”并在那里应用逻辑。

    我会选择选项 3,因为它更简单、更快。举个例子,在 Inputs 模型定义中添加以下代码

    def save(self, *args, **kwargs):
         name= self.name
         if name.endswith("S.L"):
             self.country = 'Company country'
             self.foundation_year = 'Company year'
        .... And so on ...........
         super().save(*args, **kwargs)
    

    上述代码的工作原理是,对于每个传入的数据,它都会检查名称是否以“S.L”结尾并更改逻辑。

    您可以更改视图逻辑并应用此条件,但如果您不想更改当前视图定义,也可以这样做。

    如果你想尝试选项 2,那么,试试这个

    if request.method == 'POST':
    
        Inputs = InputsForm(request.POST)
    
        if Inputs.is_valid():
    
            inp = Inputs.save(commit=False)
            inp.author = request.user
            inp.email = request.user.email
    
            # CODE -----------------------
            name = inp.name
            if name.endswith("S.L"):
               inp.country = 'Company country'
               inp.foundation_year = 'Company year'
    
              .... And so on ...........
            #CODE ! ----------------------             
    
            data = {'email': request.user.email, **Inputs.cleaned_data}
            obtain_calculate_create_send(data)
    
            inp.save()
            messages.success(request, f'Your form is valid!')
            return redirect('result/' + str(inp.pk) + '/')
        else:
            messages.warning(request, f'Please, check the inputs and enter valid ones')
    
        content = {'Inputs': Inputs, 'title': 'valuations'}
    
    else:
        Inputs = InputsForm(request.POST or None)
        content = {'Inputs': Inputs, 'title': 'valuations'}
    
    return render(request, 'valuations/form_home.html', content)
    

    【讨论】:

    • 嗨,问题是,如果它提交的表单,这将起作用,但我需要的是显示给用户的字段会根据输入动态变化,而无需提交该输入。例如,您填写一个字段,然后出现新字段而不提交,然后您提交所有已填写的字段,其余字段显示为空值或默认值。
    猜你喜欢
    • 2015-08-02
    • 1970-01-01
    • 2015-01-01
    • 2021-07-27
    • 2019-05-05
    • 2018-09-04
    • 2021-12-03
    • 2020-02-13
    • 2023-03-26
    相关资源
    最近更新 更多