在Django中的ModelForm中绑定FormSet

时间:2017-02-14 18:54:37

标签: python django django-forms inline-formset

我正在编写一个用于管理医疗保健计划的应用程序,用于管理过敏,糖尿病等行为。

我有一个表单,我可以成功创建新记录,但在更新数据时我遇到了问题。我的问题是,我不确定在打开UpdateView时如何将我的表单集绑定到保存的数据。我目前的策略是遵循here找到的答案,但我不确定在这种情况下它是否是正确答案。

现在,当我尝试转到PlanUpdateView网址时,我在medication_form_set = MedicationFormSet()(queryset=medication_queryset)上收到以下错误:

builtins.TypeError
TypeError: 'MedicationFormFormSet' object is not callable

forms.py

from django import forms
from django.forms.models import inlineformset_factory

from .models import Allergy, Medication, Allergen


class AllergyPlanForm(forms.ModelForm):
    class Meta:
        model = Allergy
        widgets = {
            'asthma': forms.RadioSelect,
            'allow_carry': forms.RadioSelect,
            'self_carry_admin': forms.RadioSelect,
        }
        fields = ('asthma', 'allow_carry', 'self_carry_admin', 'hc_provide_sign', 'par_provide_sign')


MedicationFormSet = inlineformset_factory(Allergy, Medication,
                                          fields=('dose', 'med_type', 'name_brand', 'side_effects'),
                                          extra=1)
AllergenFormSet = inlineformset_factory(Allergy, Allergen,
                                        fields=('allergen', 'insect_stings', 'other_text'),
                                        extra=1,)

models.py

from django.db import models
from django.urls import reverse


class Allergy(models.Model):
    id = models.AutoField(primary_key=True)
    student = models.ForeignKey('powerschool_schema.Student', db_column='studentsdcid')
    asthma = models.BooleanField(choices=(
        (True, 'Yes (if yes, high risk for severe reaction, please also complete IHP101.1 form)'),
        (False, 'No'),
    ), default='Unspecified')
    allow_carry = models.BooleanField(choices=(
        (True, 'It is medically appropriate for the student to self-carry Epinephrine Auto Injector (EAI) medication.'),
        (False, 'It is not medically appropriate to carray and self-administer this EAI medication.')
    ), default='Unspecified')
    self_carry_admin = models.BooleanField(choices=(
        (True, 'Student can self-carry and self-administer EAI if needed, when able and appropriate.'),
        (False, 'Student can self-carry, but not self-administer EAI.')
    ), default='Unspecified')
    hc_provide_sign = models.BooleanField(verbose_name='Healthcare Provider Signature Provided')
    par_provide_sign = models.BooleanField(verbose_name='Parent Signature Provided')

    def get_absolute_url(self):
        return reverse('health-care-plan:update', kwargs={
            'student_dcid': self.student.dcid,
            'plan_type': self._meta.verbose_name,
            'plan_id': self.id})

    class Meta:
        managed = False
        db_table = 'U_ALLERGY'
        verbose_name = 'allergy'
        verbose_name_plural = 'allergies'


class Medication(models.Model):
    id = models.AutoField(primary_key=True)
    allergy = models.ForeignKey(Allergy, db_column='u_allergyid')
    dose = models.CharField(max_length=40)
    med_type = models.CharField(max_length=100)
    name_brand = models.CharField(max_length=80)
    side_effects = models.CharField(max_length=4000)

    class Meta:
        managed = False
        db_table = 'U_MEDICATION'


class Allergen(models.Model):
    id = models.AutoField(primary_key=True)
    allergy = models.ForeignKey(Allergy, db_column='u_allergyid')
    allergen = models.CharField(max_length=1000)
    insect_stings = models.CharField(max_length=400)
    other_text = models.CharField(max_length=100)

    class Meta:
        managed = False
        db_table = 'U_ALLERGEN'

views.py

class PlanUpdateView(UpdateView):
    template_name = 'health_care_plan/plan-create.html'

    def get(self, request, *args, **kwargs):
        allergy = get_object_or_404(Allergy, id=self.kwargs.get('plan_id'))
        form = self.get_form_class(allergy)
        medication_queryset = Medication.objects.filter(allergy=allergy)
        medication_form_set = MedicationFormSet()(queryset=medication_queryset)
        allergen_queryset = Allergen.objects.filter(allergy=allergy)
        allergen_form_set = AllergenFormSet()(queryset=allergen_queryset)

        student_dcid = self.kwargs.get('student_dcid')
        student = get_object_or_404(Student, dcid=student_dcid)
        plan_type = self.kwargs.get('plan_type')

        return self.render_to_response(
            self.get_context_data(student=student,
                                  plan_type=plan_type,
                                  form=form,
                                  medication_form_set=medication_form_set,
                                  allergen_form_set=allergen_form_set))

    def get_form_class(self, plan_object):
        plan_type = self.kwargs.get('plan_type')
        if plan_type == 'allergy':
            return AllergyPlanForm(instance=plan_object)

    def get_queryset(self):
        plan_type = self.kwargs.get('plan_type')
        if plan_type == 'allergy':
            return Allergy.objects.all()

修改

更改我的观看代码
medication_queryset = Medication.objects.filter(allergy=allergy)
medication_form_set = MedicationFormSet()(queryset=medication_queryset)

allergen_queryset = Allergen.objects.filter(allergy=allergy)
allergen_form_set = AllergenFormSet()(queryset=allergen_queryset)

medication_queryset = Medication.objects.filter(allergy=allergy)
medication_form_set = MedicationFormSet(queryset=medication_queryset)

allergen_queryset = Allergen.objects.filter(allergy=allergy)
allergen_form_set = AllergenFormSet(queryset=allergen_queryset)

现在给了我这个错误:

AttributeError: 'PlanUpdateView' object has no attribute 'object'

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/django/contrib/staticfiles/handlers.py", line 63, in __call__
    return self.application(environ, start_response)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/wsgi.py", line 170, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in get_response
    response = self._middleware_chain(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 86, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 128, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/usr/local/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/six.py", line 686, in reraise
    raise value
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/utils/deprecation.py", line 136, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 86, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 128, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/usr/local/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/six.py", line 686, in reraise
    raise value
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/utils/deprecation.py", line 136, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 86, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 128, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/usr/local/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/six.py", line 686, in reraise
    raise value
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/utils/deprecation.py", line 136, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 86, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 128, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/usr/local/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/six.py", line 686, in reraise
    raise value
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/utils/deprecation.py", line 136, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 86, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 128, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/usr/local/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/six.py", line 686, in reraise
    raise value
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/utils/deprecation.py", line 136, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 86, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 128, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/usr/local/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/six.py", line 686, in reraise
    raise value
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/utils/deprecation.py", line 136, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 86, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 128, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/usr/local/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/six.py", line 686, in reraise
    raise value
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/utils/deprecation.py", line 136, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 86, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 128, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/usr/local/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/six.py", line 686, in reraise
    raise value
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/utils/deprecation.py", line 136, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 86, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 128, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/usr/local/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 6, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/six.py", line 686, in reraise
    raise value
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.6/contextlib.py", line 53, in inner
    return func(*args, **kwds)
  File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py", line 88, in dispatch
    return handler(request, *args, **kwargs)
  File "/app/powerschool_apps/health_care_plan/views.py", line 142, in get
    allergen_form_set=allergen_form_set))
  File "/usr/local/lib/python3.6/site-packages/django/views/generic/edit.py", line 94, in get_context_data
    return super(FormMixin, self).get_context_data(**kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/views/generic/detail.py", line 101, in get_context_data
    if self.object:
AttributeError: 'PlanUpdateView' object has no attribute 'object'

2 个答案:

答案 0 :(得分:0)

Alasdair的建议有所帮助,但同样有帮助的是将self.object分配给我试图绑定表单的对象。

class PlanUpdateView(UpdateView):
    template_name = 'health_care_plan/plan-create.html'

    def get(self, request, *args, **kwargs):
        self.object = get_object_or_404(Allergy, id=self.kwargs.get('plan_id'))
        plan_type = self.kwargs.get('plan_type')
        form = self.get_form_class(self.object)
        medication_form_set = MedicationFormSet(instance=self.object)
        allergen_form_set = AllergenFormSet(instance=self.object)

        student_dcid = self.kwargs.get('student_dcid')
        student = get_object_or_404(Student, dcid=student_dcid)

        return self.render_to_response(
            self.get_context_data(student=student,
                                  plan_type=plan_type,
                                  form=form,
                                  medication_form_set=medication_form_set,
                                  allergen_form_set=allergen_form_set))

    def get_form_class(self, plan_object):
        plan_type = self.kwargs.get('plan_type')
        if plan_type == 'allergy':
            return AllergyPlanForm(instance=plan_object)

    def get_queryset(self):
        plan_type = self.kwargs.get('plan_type')
        if plan_type == 'allergy':
            return Allergy.objects.all()

    def get_success_url(self):
        reverse('health-care-plan:index', kwargs={'students_dcid': self.kwargs.get('student_dcid')})

答案 1 :(得分:0)

我今天刚刚解决这个问题,我使用了model_to_dict。这是我的代码:

from django.forms.models import model_to_dict

@login_required
def edit_profile(request):
    profile = ClientProfile.objects.get(user_id=request.user.id)
    if request.method == 'POST':
        form = ProfileSubmissionForm(request.POST, instance=profile)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('jobs:list'))
    else:
        profile_dict = model_to_dict(profile)
        form = ProfileSubmissionForm(profile_dict)
        return render(request, 'jobs/profile.html', {'form': form})

请注意,我已将profile传递给model_to_dict

这有帮助吗?