There are similar issues on SO, but none alike this.
I would like to update a field in a record of a m2m model which has a unique constraint on
training. This model is defined as (
class Occurrence(models.Model): attendee = models.ForeignKey(Attendee, on_delete=models.CASCADE) training = models.ForeignKey(Training, on_delete=models.CASCADE) attended_date = models.DateField(default=date(1900, 12, 31)) class Meta: constraints = [ models.UniqueConstraint(fields=['attendee', 'training'], name='unique_attendee_training') ]
Now, consider e.g. that John has taken the Python course and already exists as record in the db. If I try get the date of when the training occurred, I would go like this:
from trainings.models import Attendee, Training, Occurrence from datetime import date, datetime attendee = Attendee.objects.get(firstname.lastname@example.org') training = Training.objects.get(pk='python310') occurrence = Occurrence.objects.get(attendee=attendee, training=training) print(occurrence.attended_date) # datetime.date(2021, 11, 4)
However, if I try to update the date of this record, I get the error.
occurrence = Occurrence(attendee=attendee, training=training, attended_date=date(2021, 11, 5)) occurrence.save(update_fields=["attendee", "training", "attended_date"])
The error being:
ValueError: Cannot force an update in save() with no primary key.
How do I update this record?
I believe this should be enough to understand the question. But if you want to reproduce the whole issue, I post here the models (
model.py) for Attendees and Trainings.
class Attendee(models.Model): first_name = models.CharField('First Name', max_length=30, blank=False) last_name = models.CharField('Last Name', max_length=30, blank=False) email = models.EmailField("Email Address", max_length=75, blank=False, primary_key=True)
class Training(models.Model): long_name = models.CharField('Training Name', max_length=80, blank=False, null=False) short_name = models.CharField('Abbreviation', max_length=10, blank=False, null=False, primary_key=True) description = models.TextField('Descriprion', blank=True) alumni = models.ManyToManyField(Attendee, through='Occurrence')
short_name as pk. With
alumni that relates
You are updating the record in the wrong way,
occurrence = Occurrence.objects.get(attendee=attendee, training=training) print(occurrence.attended_date) # # datetime.date(2021, 11, 4) # update the record like this occurrence.attended_date = date(2021, 11, 5) occurrence.save()
You can tell Django to update specific fields by passing the
update_fields parameter, as
# Use instead of `occurrence.save()` occurrence.save(update_fields=["attended_date"])