mrhaoji
mrhaoji

Reputation: 336

Update a table when other tables changed in Django ORM

Models.py

# store the number of new Videos that added to a Album
class Badge(models.Model):
    user_id = models.IntegerField()  # the user you wanna inform
    album_id = models.IntegerField()
    count = models.IntegerField(blank=True, null=True)
    update_time = models.DateTimeField(blank=True, null=True)

# a Album has several videos in it, and will be updated 
class Album(models.Model):
    title = models.CharField(max_length=100, default='', null=True)
    update_time = models.DateTimeField(blank=True, null=True)

class Video(models.Model):
    title = models.CharField(max_length=100, default='', null=True)
    aid = models.ForeignKey(Album, on_delete=models.CASCADE, default='')
    update_time = models.DateTimeField(blank=True, null=True)

Suppose in the database:

Album table:

357 Learning_Django 2018-07-02 12:40:03.041558

Video table:

1 Install_Python 357 2018-07-02 12:40:03.041558
2 Install_pip 357 2018-07-02 12:40:03.041558
3 Install_Django 357 2018-07-02 12:40:03.041558

Now, two new video has been insert into the Video table:

1 Install_Python 357 2018-07-02 12:40:03.041558
2 Install_pip 357 2018-07-02 12:40:03.041558
3 Install_Django 357 2018-07-02 12:40:03.041558
4 Create_Django_Project 357 2018-07-13 08:40:03.041558
5 Define_Django_Models 357 2018-07-13 08:40:03.041558

What should I do to let this update reflect on Badge table (insert/update a record), like this:

1 001 357 2 2018-07-13 08:40:03.041558

It means that the Album #357 has been updated with 2 videos, and it will inform the user #001.

Thanks for your help.

Upvotes: 0

Views: 1748

Answers (2)

Ykh
Ykh

Reputation: 7717

I think signal is what you need,demo like this

signals.py:

from django.db.models.signals import post_save
from django.dispatch import receiver

from .models import User, Video, Badge

@receiver(post_save, sender=Video)
def create_badge(sender, instance=None, created=False, **kwargs):
    if created:
        badge, is_created = Badge.objects.get_or_create(user_id='user id you want inform', album_id=instance.aid.id, defaults={'count': 0})
        badge.count += 1
        badge.save()

apps.py:

from django.apps import AppConfig


class UserConfig(AppConfig):
    name = 'user'

    def ready(self):
        import user.signals

__init__.py:

default_app_config = 'user.apps.UserConfig'

Change User or user to your own app_name

Upvotes: 2

seuling
seuling

Reputation: 2956

As @Ykh said, signal is the best way.

Also you can use model's save method. You can check more detail in docs

Here's demo (Actually I can't understand what you want to do, so it's just reference)

class Video(models.Model):
    title = models.CharField(max_length=100, default='', null=True)
    aid = models.ForeignKey(Album, on_delete=models.CASCADE, default='')
    update_time = models.DateTimeField(blank=True, null=True)

    def save(self, *args, **kwargs):
        # do this only when created
        if not self.pk:
            # do something you want like
            badge, is_created = Badge.objects.get_or_create(user_id='user id you want inform', album_id=self.aid.id, defaults={'count': 0})
            badge.count += 1
            badge.save()
        super().save(*args, **kwargs)

Upvotes: 1

Related Questions