0

I have a visit-create class based on a CreateView. It accesses the organization from the URL, so it's passed in as a keyword arg.

class VisitCreate(LoginRequiredMixin, UserOrgRequiredMixin, CreateView):
    model = models.Visit
    form_class = VisitCreateForm
    # template_name is "visit_form.html" from CreateView

    def form_valid(self, form):
        # get the patient for this visit
        patient = models.Patient.get_by_pk(self.kwargs['patientId'])
        if not patient or patient.organization.name != self.kwargs['orgStr']:
            raise SuspiciousOperation('Patient does not exist')

I want to write a form field validator that checks something about the visit, but it needs the orgStr. Here is the current form field validator, but it can't get the orgStr:

class VisitCreateForm(ModelForm):
    class Meta:
        model = models.Visit
        ...
    # Allow only one visit per day
    def clean_visit_date(self):
        visit_date = self.cleaned_data['visit_date']
        if models.Visit.get_visits(visit_date, visit_date, self.kwargs['orgStr']):
            raise ValidationError('There is already a visit on this date')

How do I mark a field error on visit_date? Either I have to pass orgStr to the form somehow, or mark the field error in VisitCreate.form_valid.

Please don't suggest adding the orgStr as a hidden field in the form. That seems crazy.

1
  • I would try to keep the validation in the form. You can add errors in the form_valid() method with form.add_error(...), but then you need to handle your invalid form (e.g. by returning self.form_invalid(...)), which complicates the flow of the code. Commented Apr 9, 2018 at 15:19

1 Answer 1

2

You can override the view's get_form_kwargs method to pass orgStr from the URL:

class VisitCreate(LoginRequiredMixin, UserOrgRequiredMixin, CreateView):
    def get_form_kwargs(self):
        kwargs = super(VisitCreate, self).get_form_kwargs()
        kwargs['orgStr'] = self.kwargs['orgStr']
        return kwargs

You then need to override the form's __init__ method to handle orgStr.

class VisitCreateForm(ModelForm):
    ...

    def __init__(self, *args, **kwargs):
        self.orgStr = kwargs.pop('orgStr')
        super(VisitCreateForm, self).__init__(*args, **kwargs)

    # You can now access `self.orgStr` in the `clean_visit_date` method.
    def clean_visit_date(self):
        visit_date = self.cleaned_data['visit_date']
        if models.Visit.get_visits(visit_date, visit_date, self.orgStr):
            raise ValidationError('There is already a visit on this date')
Sign up to request clarification or add additional context in comments.

1 Comment

You sir are a gentleman and a scholar. If only I could give you more than one upvote.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.