from django.forms import ( BaseInlineFormSet, Form, ModelForm, ModelMultipleChoiceField, ModelChoiceField, ChoiceField, CharField, ) from django.forms import inlineformset_factory from generic.forms import ExamAuthorFormMixin, ExamFormMixin, ExamGroupsFormMixin, ExamMarkerFormMixin from longs.models import ( # Examination, AnswerMarks, Long, LongSeries, LongSeriesImage, LongCreationDefault, UserAnswer, Exam, ) from django.db.models import Prefetch from anatomy.models import Modality from generic.models import Examination#, Condition, Sign # from generic.models import Examination, Site, Condition, Sign from django.contrib.admin.widgets import FilteredSelectMultiple from django.forms.widgets import RadioSelect, TextInput, Textarea from tinymce.widgets import TinyMCE from generic.widgets import ExamSearchWidget class LongAnswerForm(ModelForm): class Meta: model = UserAnswer fields = ( "answer_observations", "answer_interpretation", "answer_principle_diagnosis", "answer_differential_diagnosis", "answer_management", ) class MarkLongQuestionSingleForm(ModelForm): class Meta: model = UserAnswer fields = ["score", "candidate_feedback"] widgets = { "candidate_feedback": Textarea(attrs={"rows": 3}), } class MarkLongQuestionDoubleForm(ModelForm): class Meta: model = AnswerMarks fields = ["score", "mark_reason"] class ExaminationForm(ModelForm): class Meta: model = Examination fields = ["examination"] class LongCreationDefaultForm(ModelForm): class Meta: model = LongCreationDefault # fields = ["site"] exclude = ["author"] class LongSeriesForm(ModelForm): class Media: # Django also includes a few javascript files necessary # for the operation of this form element. You need to # include # in the template. css = { "all": ["css/widgets.css"], } # Adding this javascript is crucial js = ["jsi18n.js", "tesseract.min.js"] def __init__(self, *args, **kwargs): self.user = kwargs.pop( "user" ) # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole if kwargs.get("instance"): # We get the 'initial' keyword argument or initialize it # as a dict if it didn't exist. initial = kwargs.setdefault("initial", {}) # The widget for a ModelMultipleChoiceField expects # a list of primary key for the selected data. initial["long"] = [t.pk for t in kwargs["instance"].long.all()] super(LongSeriesForm, self).__init__(*args, **kwargs) # self.fields["examination"] = ModelChoiceField( # queryset=Examination.objects.all(), # widget=FilteredSelectMultiple(verbose_name="Examination", is_stacked=False), # ) self.fields["modality"] = ModelChoiceField( required=True, queryset=Modality.objects.all(), ) ModelForm.__init__(self, *args, **kwargs) if self.user.groups.filter(name="long_checker").exists(): long_queryset = Long.objects.all() else: long_queryset = Long.objects.filter( author__id=self.user.id ) | Long.objects.filter(open_access=True) self.fields["long"] = ModelMultipleChoiceField( required=False, queryset=long_queryset, widget=FilteredSelectMultiple(verbose_name="Long", is_stacked=False), ) def save(self, commit=True): # Get the unsaved Pizza instance instance = ModelForm.save(self, False) # Prepare a 'save_m2m' method for the form, old_save_m2m = self.save_m2m def save_m2m(): old_save_m2m() # This is where we actually link the pizza with toppings instance.long.clear() for long in self.cleaned_data["long"]: instance.long.add(long) self.save_m2m = save_m2m # Do we need to save all changes now? # if commit: instance.save() self.save_m2m() return instance class Meta: model = LongSeries exclude = ["author"] class LongForm(ModelForm): # exams = ModelMultipleChoiceField(required=False, queryset=Exam.objects.all(),widget=FilteredSelectMultiple(verbose_name="Exams", is_stacked=False)) class Media: # Django also includes a few javascript files necessary # for the operation of this form element. You need to # include # in the template. css = { "all": ["css/widgets.css"], } # Adding this javascript is crucial js = ["jsi18n.js", "tesseract.min.js"] def __init__(self, *args, **kwargs): self.user = kwargs.pop( "user" ) # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole if kwargs.get("instance"): # We get the 'initial' keyword argument or initialize it # as a dict if it didn't exist. initial = kwargs.setdefault("initial", {}) # The widget for a ModelMultipleChoiceField expects # a list of primary key for the selected data. initial["exams"] = [t.pk for t in kwargs["instance"].exams.all()] ModelForm.__init__(self, *args, **kwargs) super(LongForm, self).__init__(*args, **kwargs) print(self.fields) if self.user.groups.filter(name="long_checker").exists(): exam_queryset = Exam.objects.all() else: exam_queryset = Exam.objects.filter( author__id=self.user.id ) | Exam.objects.filter(open_access=True) self.fields["exams"] = ModelMultipleChoiceField( required=False, queryset=exam_queryset, widget=ExamSearchWidget(exam_model=Exam), ) class Meta: model = Long # fields = ['due_back'] # fields = '__all__' fields = [ # "examination", # "site", "description", "history", "feedback", #"condition", #"sign", "model_observations", "model_interpretation", "model_principle_diagnosis", "model_differential_diagnosis", "model_management", "mark_scheme", "open_access", ] # fields = ['question', 'feedback', 'subspecialty', 'references'] widgets = { # "normal": RadioSelect( # choices=[(True, 'Yes'), # (False, 'No')]) "feedback": TinyMCE(attrs={"cols": 80, "rows": 20}), "mark_scheme": TinyMCE(attrs={"cols": 80, "rows": 30}), "description": Textarea(attrs={"cols": 80, "rows": 5}), "history": Textarea(attrs={"cols": 80, "rows": 5}), "model_observations": Textarea(attrs={"cols": 80, "rows": 5}), "model_interpretation": Textarea(attrs={"cols": 80, "rows": 5}), "model_principle_diagnosis": Textarea(attrs={"cols": 80, "rows": 5}), "model_differential_diagnosis": Textarea(attrs={"cols": 80, "rows": 5}), "model_management": Textarea(attrs={"cols": 80, "rows": 5}), } def save(self, commit=True): instance = ModelForm.save(self, False) instance.save() old_exams = instance.exams.all() new_exams = self.cleaned_data["exams"] for exam in old_exams: if exam not in new_exams: exam.exam_questions.remove(instance) for exam in new_exams: exam.exam_questions.add(instance) self.save_m2m() return instance #class CustomInlineFormSet(BaseInlineFormSet): # def get_queryset(self): # if not hasattr(self, '_queryset'): # qs = super(CustomInlineFormSet, self).get_queryset()#.values() # self._queryset = qs # return self._queryset #class LongForm(ModelForm): class CaseSeriesForm(ModelForm): def __init__(self, *args, **kwargs): super(CaseSeriesForm, self).__init__(*args, **kwargs) ModelForm.__init__(self, *args, **kwargs) # We can limit the series available to choose from here # as well a dramatically reducing the sql queries queryset = LongSeries.objects.select_related("modality", "examination", "plane").prefetch_related("long").all()#.filter(pk=62)#.values() self.fields["longseries"] = ModelChoiceField(queryset=queryset) class Meta: model = LongSeries.long.through #fields = [ modality ] #exclude = [] fields = ["longseries", "sort_order"] SeriesFormSet = inlineformset_factory( Long, LongSeries.long.through, form=CaseSeriesForm, exclude=[], can_delete=True, extra=0, max_num=10, #formset=CustomInlineFormSet ) LongSeriesImageFormSet = inlineformset_factory( LongSeries, LongSeriesImage, exclude=[], can_delete=True, extra=0, max_num=2000, field_classes="testing", ) class ExamForm(ExamFormMixin, ModelForm): class Meta(ExamFormMixin.Meta): model = Exam fields = ExamFormMixin.Meta.fields + ["double_mark"] class ExamAuthorForm(ExamAuthorFormMixin): class Meta(ExamAuthorFormMixin.Meta): model = Exam #fields = ExamAuthorFormMixin.Meta.fields.append("double_mark") class ExamMarkerForm(ExamMarkerFormMixin): class Meta(ExamMarkerFormMixin.Meta): model = Exam class ExamGroupsForm(ExamGroupsFormMixin): class Meta(ExamGroupsFormMixin.Meta): model = Exam