J
J
JBlasck2020-06-08 15:15:05
Django
JBlasck, 2020-06-08 15:15:05

Django. How to save a form with model instance binding without losing the values ​​of fields not specified in the form?

When writing a form with a bound instance of the instance model , the values ​​of the entity fields that were not part of the form and, accordingly, did not come in the POST request, but were present in the instance at the time of initialization, are reset.

Users can enter data into the form: Operators - the name , number fields , OTK - the allow field and Managers - all fields of the model form. As you can see, only a part of the fields are present for the Operator and OTK in the form (the presence of fields is limited by the means of the html template). But, when the Operator or DTC edits a form with an instance model instance with all initialized data, the values ​​of the remaining fields are allow ,date and time , except for the ticket file field, are set to zero when the form is written, although they are present in instance .

In this connection questions:
1. Whether it is normal such behavior of the form with instance to erase contents of the fields which are not participating in POST?
2. How, in this case, to bypass the problem of information loss and provide the possibility of partial and complete editing of the form while saving the rest of the data.
3. Perhaps there are generally accepted approaches to solving such a standard situation, tell me, please ..?

Model:

class Entry(models.Model):
    # поля Оператора 
    name = models.CharField(max_length=20, blank=True)
    number = odels.CharField(max_length=10, blank=True)
    # поле ОТК
    allow = models.NullBooleanField(default=None, choices=((None, 'Нет'), (True, 'Да'), (False, 'Отказ')))
    # поля Менеджера + все вышеуказанные
    date = models.DateField(blank=True, null=True) 
    time = models.TimeField(blank=True, null=True)
    ticket = models.FileField(blank=True, null=True, upload_to='tickets/')


The form:
class Form(forms.ModelForm):
    class Meta: 
        model = Entry
        fields = ['name', 'number', 'allow', 'date', 'time', 'ticket']


view:
def edit_form(request, pk=None):
    staff = request.user.staff
    entry = Entry.objects.filter(id=pk).first()
    entryForm = Form(request.POST or None, request.FILES or None, instance = entry)

    if request.method == "POST" and entryForm.is_valid():
        entryForm.save()
        redirect(search_entry(request))
    else:
        render(request, 'template.html', {'entryForm': entryForm, 'staff': staff})


HTML template:
<div class="form-control">
    {%for field in entryForm %}
        {%if staff.is_operator and forloop.counter < 3 or staff.is_otk and forloop.counter == 3 or staff.is_manager%}
            <label>{{field.label_tag}}</label>
            <p>{{field}}</p>
        {%endif%}
    {%endfor%}
</div>

Answer the question

In order to leave comments, you need to log in

2 answer(s)
D
Dr. Bacon, 2020-06-08
@bacon

To prevent them from being nulled, exclude them from fields in the form, i.e. for each user type, either create your own form or automatically generate fields depending on the type

J
JBlasck, 2020-06-10
@JBlasck

Implemented as follows:
Initializing and writing the form:
View:

def edit_form(request, pk=None):
    staff = request.user.staff
    entry = Entry.objects.filter(id=pk).first()
    if staff.is_operator:  fields = ['name', 'number']
    if staff.is_otk:  fields = ['allow']
    if staff.is_manager:  fields = ['name', 'number', 'allow', 'date', 'time', 'ticket']
    # инициализация
    form = modelform_factory(Entry, form=miniForm, fields=fields)
    entryForm = form(data=request.POST or None, files=request.FILES or None, instance=entry)
    # запись
    if request.method == "POST" and entryForm.is_valid():
        entryForm.save()
        redirect(search_entry(request))
    else:
        render(request, 'template.html', {'entryForm': entryForm, 'staff': staff})

forms:
class miniForm(forms.ModelForm):
    class Meta:    
        model = Entry 
        # поля добавляются параметром 'fields' через 'modelform_factory()'
        fields = []

HTML:
<div class="form-control">
    {% for field in entryForm %}
        <label>{{field.label_tag}}</label>
        <p>{{field}}</p>
    {%endfor%}
</div>

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question