Search code examples
djangosignalsmodels

Field of a model upadated by another model django


I have a model lets say customer. And i want to add a field to that customer lets say next_meeting. It will be a datetime field, and will have the date of the next meeting with the customer. I also have a Meeting model that has a date field of type datetimeField again. So they look something like that.

class Customer(models.Model):
    ....fields....
    next_meeting = models.DateTimeField(blank=True, null=True)


class Meeting(models.Model):
    ....fields....
    date = models.DateTimeField(auto_now_add = True)
    customer = models.ForeignKey(Customer, related_name='meetings')

I want the customer.next_meeting field to contain the most recent date of all the next meetings. So I was thinking doing a post save signal that would take the date of the meeting, and

1. Check if customer.next_meeting is null (first meeting). If null set next_meeting to meeting.date
2. If not null check if meeting.date < customer.next_meeting. If true update customer.next_meeting

The same must be done for the post delete signal(if a meeting is deleted).

1. get the most recent meeting after current date for customer using order_by('date')[0]
2. If meeting: update the next_meeting field, else(no meetings) leave blank.

Is this correct way to do this. It sounds a bit too "expensive" if you have a lot of meetings for a customer database side expensive. Or am I mistaken?


Solution

  • When you design your database structure you should make sure you don't repeat the same information in multiple places - i.e. that the database in normalized. Get rid of the next_meeting field all together, you can still get the information with the right query:

    Get the most recent meeting for customer with id customer_id:

    Meeting.objects.filter(customer=customer_id).order_by('date').first()
    

    Add most recent meeting date to every user in a queryset:

    Customer.objects.annotate(next_meeting=Min('meeting__date'))
    

    This assumes there are no past meetings in the database - because your solution also required that is the case. If it is not you would obviously need one more filter, to filter out meetings in the past.