Django ModelForm 初始或自定义字段值

dev*_*ink 1 python django django-models django-forms django-views

我有一个简单的模型,甚至更简单的模型表单,但我无法弄清楚如何为表单字段设置初始值或自定义值。

我试过form.cleaned_data['fieldname'] = value, initial={'field':value}, form.fields['field'].initial = value,甚至像这样索引它,form.cleaned_data['status'] = Locked.STATUS[0][0]但我无法让它工作。

作为记录,我想使用我的模型中的选择字段。字段名称是'STATUS',我想在views.py 中设置第一个值('odlozen') 用作表单字段值。所以 form.cleaned_data 需要是 'odlozen' 的 STATUS 值,当这个函数触发时。

附注。不要介意我没有声明我的整个代码,因为这个问题没有必要。谢谢!

让我们从我的代码开始:

模型.py

class Locked(models.Model):
    STATUS = (
        ('odlozen', 'Odložen'),    #this is the value
        ('u_procesu', 'U procesu'),
        ('ne_javlja_se', 'Ne javlja se'),
        ('zakazan', 'Zakazan'),
        ('odustao', 'Odustao'),
        ('default', 'Izaberite status.'),
    )
    ...
    opp_comment = models.CharField(max_length=155, blank=True)
    status = models.CharField(max_length=50, choices=STATUS, blank=True)    #I set blank=True for no reason, it can be False also. 
    ...

    class Meta:
        verbose_name = 'Locked'
        verbose_name_plural = 'Locked'
        get_latest_by = 'locked_name'

    def __str__(self):
        return smart_str(self.locked_eluid)
Run Code Online (Sandbox Code Playgroud)

这是我的 forms.py :

class OppDetaljiForm(forms.ModelForm):
    class Meta:
        model = Locked

        fields = [... ,'status','opp_comment', ...]
        labels = {
            ...
            'opp_comment': 'Comment',
            'status': 'Status',
            ...
        }
        widgets = {
            ...
            'status': forms.HiddenInput(),
            'opp_comment': forms.Textarea()

        }
Run Code Online (Sandbox Code Playgroud)

我的 view.py :

def odlozi(request, pk):
    opp_locked = Locked.objects.get(pk=pk)
    form = OppDetaljiForm(instance=opp_locked)
    ...

    if request.method == 'POST':
        form = OppDetaljiForm(request.POST or None, instance=opp_locked, initial={'status': 'odlozen'})

        if form.is_valid():
            form.cleaned_data['status'] = 'odlozen'    #?! As I said before, none of my ideas worked.
            ...
            form.save()
            ...

            return redirect('appname:url')    # Dont mind me for not declaring my code, since it not necessary
    context = {
        'form': form,
        ...
    }
    return render(request, 'myhtmlpage.html', context)
Run Code Online (Sandbox Code Playgroud)

这是 HTML :

<div class="container" style="position: relative">
        <form action="" method="POST">
            {% csrf_token %}
            <div class="form-row my-4">
                <div class="form-group col-md-6 mb-0">
                    {{ form.status|as_crispy_field }}
                </div>
                <div class="form-group col-md-12 mb-0">
                    {{ form.opp_comment|as_crispy_field }}
                </div>
                ...
                   # Other form fields    
                ...
            </div>
            <a class="btn btn-light" href="{% url 'appname:url' %}">Back</a>
            <button type="submit" class="btn btn-primary" style="float: right">Submit</button>
        </form>
    </div>
Run Code Online (Sandbox Code Playgroud)

dir*_*ten 6

有几种方法:

  • 如果在你的模型中你设置了一个默认值,afaik 它将被用作相应的初始值 ModelForm
  • 或者只是将initial字典传递给表单的初始化程序:
    form = OppDetaljiForm(instance=opp_locked, initial={'status': 'odlozen'})
    
    Run Code Online (Sandbox Code Playgroud)

但是请注意,由于您正在传递一个实例 ( opp_locked),因此从实例中获取的值将取代来自 的值initial。

你所说的初始值是当用户没有选择任何开始时在表单中显示给用户的字段的值。这与在用户提交表单(忽略用户输入)后覆盖该值不同。您可以在该字段的表单的 clean 方法中执行此操作:

# in OppDetaljiForm
def clean_status(self):
    status = self.cleaned_data.get('status')
    if not status:
        status = 'odlozen'
    return status
Run Code Online (Sandbox Code Playgroud)

最后,如果用户status无论如何都无法设置,则根本不要将其放入表单中(将其从fields模板中完全删除)并在保存模型之前将其设置在您的视图中:

if form.is_valid():
    opp_detail = form.save(commit=False)  # gives you the instance without saving it
    opp_detail.status = 'odlozen'  # add values that your form didn't set
    opp_detail.save()  # now save
Run Code Online (Sandbox Code Playgroud)

或者让表单处理它:

class OppDetaljiForm(forms.ModelForm):
     status = 'odlozen'
     class Meta:
         fields = (<list of fields without 'status'!>)
     # ...
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.instance.status = self.status  # assigns the status to the instance
Run Code Online (Sandbox Code Playgroud)

你说你有六个表单,如果唯一的区别是它们设置的状态,那么只需制作一个表单并将状态传递给 init 方法,这样在你的视图中你就可以这样做form = MyForm(request.POST, instance=..., status='odlozen')。