Python: 3.11.5
Django: 5.0.1
I have a form that saves one model fine (GlobalProject). In that form I have a a ModelMultipleChoiceField that pulls from a different model (Deals). When a new GlobalProject is created with selections made in that drop down, I want to update those models (the Deals) with a foreign key of the newly created GlobalProject. The models are not managing the database objects, that’s happening somewhere else and the actual database tables have more columns than are listed in the Django models.
I thought I was close but I keep getting the following error: Save with update_fields did not affect any rows
.
Here’s my code that is generating this:
models.py
class GlobalProject(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
name = models.CharField(unique=True, max_length=300)
is_internal = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self) -> str:
return str(self.name)
class Meta:
managed = False
db_table = "global_projects"
class Deal(models.Model):
id = models.IntegerField(primary_key=True, editable=False)
amount = models.FloatField(editable=False)
name = models.TextField(editable=False)
is_closed_won = models.BooleanField(editable=False)
global_project = models.ForeignKey(
GlobalProject, on_delete=models.SET_NULL, null=True
)
def __str__(self) -> str:
return str(self.name)
class Meta:
managed = False
db_table = "deals"
forms.py
class GlobalProjectNewForm(ModelForm):
deal_queryset = Deal.objects.order_by("name").filter(
is_closed_won=True, global_project=None
)
deal_dropdown = ModelMultipleChoiceField(
label="Link to Closed Won Deals",
widget=SelectMultiple(attrs={"class": "form-control"}),
queryset=deal_queryset,
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["deal_dropdown"].initial = self.deal_queryset.values_list(
"name", flat=True
)
def save(self, commit=True):
project = super().save(commit=commit)
deals = self.cleaned_data["deal_dropdown"]
for deal in deals:
deal.global_project = project
deal.save(update_fields=["global_project"])
return project
class Meta:
model = GlobalProject
fields = ("name", "is_internal")
views.py
def new(request):
ProjectFormSet = modelform_factory(GlobalProject, form=GlobalProjectNewForm)
if request.method == "POST":
formset = ProjectFormSet(request.POST, request.FILES)
if formset.is_valid():
instance = formset.save()
return redirect("projects:detail", project_id=instance.id)
else:
formset = ProjectFormSet()
return render(request, "projects/new.html", {"formset": formset})
After running the above and creating a POST request, a new GlobalProject object is created in the database with corresponding UUID. The associated deals are never updated and the deal.save()
is where the Save with update_fields did not affect any rows
is coming from.
Any idea on how to do what I am trying to do here? Thanks!