Django Начальное или пользовательское значение ModelForm поля - PullRequest
0 голосов
/ 04 февраля 2020

У меня есть простая модель и даже более простая форма модели, но я просто не могу понять, как установить начальное или пользовательское значение для моего поля формы.

Я пытался с form.cleaned_data['fieldname'] = value, initial={'field':value}, form.fields['field'].initial = value, даже индексировал его вот так form.cleaned_data['status'] = Locked.STATUS[0][0], но не смог заставить его работать.

Для записи я хочу использовать поле выбора из моей модели. Имя поля «STATUS», и я хочу установить первое значение («odlozen»), которое будет использоваться в качестве значения поля формы, в моем views.py. Таким образом, form.cleaned_data должен быть значением STATUS 'odlozen', когда эта функция срабатывает.

PS. Не обращайте внимания на то, что я не объявил весь мой код, поскольку в этом вопросе нет необходимости. Спасибо!

Давайте начнем с моего кода:

models.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)

Это мои формы.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()

        }

Мой 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)

А это 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>

1 Ответ

2 голосов
/ 04 февраля 2020

Есть несколько способов:

  • Если в вашей модели вы установите значение по умолчанию, afaik будет использоваться в качестве начального значения в соответствующем ModelForm
  • или просто передать initial словарь для инициализатора формы:
    form = OppDetaljiForm(instance=opp_locked, initial={'status': 'odlozen'})
    

Обратите внимание, однако, что поскольку вы передаете экземпляр (opp_locked), значение, взятое из экземпляра, заменяет значение из initial.

Исходное значение , о котором вы говорите, является значением поля, отображаемого для пользователя в форме, когда пользователь не выбрал ничего для начала. Это отличается от переопределения значения после , когда пользователь отправляет форму (игнорируя введенные пользователем данные). Вы можете сделать это в чистом методе формы для поля:

# in OppDetaljiForm
def clean_status(self):
    status = self.cleaned_data.get('status')
    if not status:
        status = 'odlozen'
    return status

Наконец, если пользователь все равно не может установить 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

Или позвольте форме обработать это:

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

Вы говорите, что у вас есть шесть формы, если единственное отличие состоит в том, какой статус они устанавливают, тогда просто создайте одну форму и передайте статус методу init, чтобы, на ваш взгляд, вы могли, например, form = MyForm(request.POST, instance=..., status='odlozen').

...