That was my understanding too. Ok, something that might be complicating this is that I’m trying to use Mixins to spread form fields across several classes so I don’t have a huge form class.
Here’s the parent form:
class GlobalProjectNewForm(
ModelForm,
HubspotDealFormMixin,
JiraProjectFormMixin,
):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
HubspotDealFormMixin.__init__(self, False)
JiraProjectFormMixin.__init__(self, False)
def save(self, commit=True):
project = super().save(commit=commit)
HubspotDealFormMixin.save_new(self, project)
JiraProjectFormMixin.save_new(self, project)
return project
class Meta:
model = GlobalProject
fields = ("name", "is_internal", "notes")
Here’s the JiraProjectMixin
class JiraProjectFormMixin(FormMixin):
__queryset = JiraProject.objects.all().order_by("name")
jira_project_selector = ModelChoiceField(
label="Link to Jira Project",
queryset=__queryset,
widget=Select(attrs={"class": "form-jira-project-selector"}),
required=False,
blank=True,
)
__FIELD_KEY = f"{jira_project_selector=}".split("=")[0]
def __init__(self, is_edit: bool = False):
if is_edit and hasattr(self.instance, "pk"):
self._initial_assigned_jira_project = JiraProject.objects.filter(
global_project_id=self.instance.pk
).values_list("id", flat=True)
self.fields[self.__FIELD_KEY].choices = self.__queryset.filter(
(
Q(global_project=None)
| Q(global_project_id=self.instance.pk)
)
& Q(is_private=False)
).values_list("id", "name")
self.fields[self.__FIELD_KEY].initial = self._initial_assigned_jira_project.first()
else:
self.__queryset = JiraProject.objects.filter(
Q(global_project=None) & Q(is_private=False)
).order_by("name")
self.fields[self.__FIELD_KEY].choices = self.__queryset.values_list("id", "name")
def save_new(self, project: GlobalProject) -> None:
jira_project = self.cleaned_data[self.__FIELD_KEY]
jira_project.global_project = project
jira_project.save(update_fields=["global_project", "updated_at"])
def save_edit(self, project: GlobalProject) -> None:
selected_jira_project = self.cleaned_data[self.__FIELD_KEY]
# There should only be 1 project...
current_jira_project = JiraProject.objects.get(
pk=self._initial_assigned_jira_project.first()
)
if selected_jira_project != current_jira_project:
if current_jira_project:
current_jira_project.global_project = None
current_jira_project.save(update_fields=["global_project", "updated_at"])
selected_jira_project.global_project = project
selected_jira_project.save(update_fields=["global_project", "updated_at"])
@property
def data_key(self) -> str:
return self.__FIELD_KEY
This actually seems to work for adding new projects and linking them to existing Jira projects in our database. There’s a similar form for editing that also works (the mixin classes get used for both.) The last piece I can’t figure out is how to get an empty selection here – there doesn’t have to be a connection between a Jira Project and a Global Project in our model. Same for HubSpot deals (but that’s a multiple choice field you’ve seen before )