Передача вызываемого параметра в поле модели по умолчанию завершается ошибкой

#python-3.x #django #django-models

Вопрос:

У меня есть модель с именем Package. В нем есть поля с именами, диагностика, лечение, тип пациента, mf и tp. Поля «Диагностика, лечение» и «тип пациента» имеют внешние ключи, определенные в отдельных отдельных классах, что делает поля «диагностика, лечение» и «Тип пациента» полями выбора. Теперь я намерен добиться того, чтобы всякий раз, когда пользователь выбирает лечение и тип patient_type из вариантов, я хотел, чтобы определенная цифра появлялась в mf в качестве значения по умолчанию. Это должно зависеть от обоих указанных выше полей. Я определил функцию, которая принимает лечение и тип пациента в качестве своих аргументов, применяет подходящие условия и возвращает соответствующую цифру. Но когда я назначаю функцию параметру по умолчанию для поля mf, запускаю миграции, открываю веб-страницу и заполняю данные в поле лечение и тип пациента, mf не возвращает желаемое значение. Что здесь происходит, есть ли что-то, что я делаю неправильно?

Модели:

 class Diagnosis(models.Model):
    diagnosis=models.CharField(max_length=30, blank=True)

    def __str__(self):
        return self.diagnosis

class Treatment(models.Model):
    treatment=models.CharField(max_length=15, blank=True)

    def __str__(self):
        return self.treatment

class PatientType(models.Model):
    patient_type=models.CharField(max_length=15, blank=True)

    def __str__(self):
        return self.patient_type


class Package(models.Model):
    rt_number=ForeignKey(Patient, on_delete=CASCADE)
    diagnosis=models.ForeignKey(Diagnosis, on_delete=CASCADE)
    treatment=ForeignKey(Treatment, on_delete=CASCADE)
    patient_type=ForeignKey(PatientType, on_delete=CASCADE)
    max_fractions=models.IntegerField(default=max_fraction(treatment, patient_type))
    total_package=models.DecimalField(max_digits=10, decimal_places=2)
 

Функция, которая добавляется к параметру по умолчанию в поле mf:

 def max_fraction(tt, ptt):
    
    if tt=='YEO5' and ptt=='RUHPE':
        return 40
    if tt=='D4EG' and ptt=='KILEU':
        return 40
    if tt=='5GED' and ptt=='IMRA':
        return 40
 

Формы:

 class DiagnosisForm(ModelForm):
    class Meta:
        model=Diagnosis
        fields='__all__'

class TreatmentForm(ModelForm):
    class Meta:
        model=Treatment
        fields='__all__'

class PatientTypeForm(ModelForm):
    class Meta:
        model=PatientType
        fields='__all__'

class PackageForm(ModelForm):
    class Meta:
        model=Package
        fields='__all__'
 

В views.py:

 def package_view(request):
    if request.method=='POST':
        fm_package=PackageForm(request.POST)
        fm_diagnosis=DiagnosisForm(request.POST)
        fm_treatment=TreatmentForm(request.POST)
        fm_patient_type=PatientTypeForm(request.POST)
        if fm_package.is_valid() and fm_diagnosis.is_valid() and fm_treatment.is_valid() and fm_patient_type.is_valid():
            diagnosis=fm_diagnosis.save()
            treatment=fm_treatment.save()
            patient_type=fm_patient_type.save()
            package=fm_package.save(False)
            package.diagnosis=diagnosis
            package.treatment=treatment
            package.patient_type=patient_type
            package.save()
            fm_package=PackageForm()
            fm_diagnosis=DiagnosisForm()
            fm_treatment=TreatmentForm()
            fm_patient_type=PatientTypeForm()
        return render (request, 'account/package.html', {'form2':fm_diagnosis, 'form3':fm_treatment, 'form4':fm_patient_type, 'form5':fm_package})
    else:
        fm_package=PackageForm()
        fm_diagnosis=DiagnosisForm()
        fm_treatment=TreatmentForm()
        fm_patient_type=PatientTypeForm()
        return render (request, 'account/package.html', {'form2':fm_diagnosis, 'form3':fm_treatment, 'form4':fm_patient_type, 'form5':fm_package})
 

Шаблон:

 <form action="" method="post" novalidate>
        {% csrf_token %}
        {{form2.as_p}}
        {{form3.as_p}}
        {{form4.as_p}}
        {{form5.as_p}}
        <input type="submit" value="Submit">
    </form>
 

URL-адреса:

 path('package/', views.package_view),
 

Пожалуйста, помогите мне здесь.

Комментарии:

1. Вы не можете работать с другими вызываемыми объектами в функции по умолчанию. A default=... — это вызываемый объект без параметров.

2. о-о-о! Итак, есть ли какой-либо другой способ достичь этого?

3. нет, если это поле NULL , вы позволяете свойству возвращать результат вызова функции , если это не None так, оно вернет значение базового поля.

4. потому что поле переименовано из max_fractions в _max_fractions . Это свойство поверх него, которое, таким образом, используется для извлечения.

5. noob87: форма никогда не заполнится, так как Django-это серверная часть: она отображает страницу. Поскольку другие поля, таким образом, неизвестны Django, он не может изменить предоставленную им страницу. В этом случае вам понадобится JavaScript для интерактивного выполнения этого.

Ответ №1:

Он default=… может работать с вызываемым объектом, но этот вызываемый объект не имеет никаких параметров.

Что может быть более элегантным решением, так это сделать поле ПУСТЫМ, а затем определить свойство, которое в случае a None определит значение, так что что-то вроде:

 class Package(models.Model):
    # …
    _max_fractions=models.IntegerField(default=None, null=True)
    # …
    
    @property
    def max_fractions(self):
        if self._max_fractions is None:
            return max_fraction(self.treatment, self.patient_type)
        return self._max_fractions

    @max_fractions.setter
    def _set_max_fractions(self, value):
        self._max_fractions = value