Как динамически обновлять начальные значения ModelForm?

Я пытаюсь создать динамическую форму, которая предварительно заполняет initial атрибут определенного поля (title), когда другое поле (checkin_type) выбрано из раскрывающегося меню.

Я использую универсальный Django CreateView, и я хотел бы сделать это путем переопределения метода post() представления таким образом, чтобы, если он получает запрос AJAX (который запускается jQuery .change() в вышеупомянутом раскрывающемся меню и содержит id из вариант выбора), он обновляет свойство initial формы title.

Вот вид, который я пробовал до сих пор (в views.py):

from django.views import generic
from .models import CheckIn, CheckInType


class CheckInCreate(generic.CreateView):
    model = CheckIn
    fields = '__all__'

    def post(self, request, *args, **kwargs):
        if request.is_ajax():
            checkin_type = CheckInType.objects.get(pk=request.POST['id'])
            form = self.get_form()
            form['title'].initial = checkin_type.title
            self.object = CheckIn.objects.create(checkin_type=checkin_type)
            return self.render_to_response(self.get_context_data(form=form))
        else:
            return super().post(request, *args, **kwargs)

Вот как выполняется запрос AJAX в шаблоне формы, называемом templates/dashboard/checkin_form.html в соответствии с соглашением об именах Django (dashboard — это имя приложения):

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js"></script>
<script>
    $(document).ready(function(){
        var csrftoken = Cookies.get('csrftoken');

        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });

        $(".auto-submit").change(function() {
            $.post({
                url: "{% url 'checkin-create' %}",
                data: {id: $(".auto-submit option:selected").val()}
            })
        });
    });
</script>


<form action="" method="post">{% csrf_token %}
    {% for field in form %}
        <div class="{% if field.name == 'checkin_type' %}auto-submit{% endif %}">
            {{ field.errors }}
            {{ field.label_tag }}
            {{ field }}
        </div>
    {% endfor %}
    <input type="submit" value="Send message" />
</form>

Вот соответствующие модели (в models.py):

from django.db import models


class CheckInType(models.Model):
    title = models.CharField(blank=True, max_length=255)
    description = models.TextField(blank=True)

    def __str__(self):
        return self.title


class CheckIn(models.Model):
    checkin_type = models.ForeignKey(CheckInType, null=True, on_delete=models.CASCADE)
    title = models.CharField(blank=True, max_length=255)
    description = models.TextField(blank=True)

    notes = models.TextField(blank=True)

    # Scheduling
    requested_date = models.DateField(blank=True, null=True)
    completed_date = models.DateField(blank=True, null=True)

Проблема в том, что когда я выбираю вариант из выпадающего меню для checkin_type, я не вижу никаких изменений в форме:

введите здесь описание изображения

Я ожидал, что в этом примере поле Title будет предварительно заполнено «1-недельная проверка». Любые идеи, почему это не работает?


person Kurt Peek    schedule 01.03.2018    source источник
comment
Проблема заключается в коде js, вы вызываете событие изменения в div, тогда как вы должны вызывать это при выборе идентификатора или класса. Во-вторых, при вызове post ajax нет метода успеха / выполнения для установки заголовка.   -  person Anup Yadav    schedule 01.03.2018
comment
На самом деле я пытаюсь установить title в методе post формы, а не в коде Javascript. Кроме того, я совершенно уверен, что id было передано, поскольку я проверил его, зайдя в отладчик (в этом примере он имеет значение 1). Проблема заключается в том, чтобы заставить форму перерисовываться желаемым образом.   -  person Kurt Peek    schedule 01.03.2018


Ответы (1)


Я думаю, что это сработает, если вы измените form['title'].initial = checkin_type.title на form.cleaned_data['title'] = checkin_type.title

person HenryM    schedule 01.03.2018
comment
Я пробовал это, и это не сработало, и в любом случае это не дало бы того же самого: initial указывает значение, используемое при отображении поля, но на самом деле это значение не установлено для поля (пока). - person Kurt Peek; 01.03.2018