(Django) 2개의 모델을 비교해 필드값 업데이트하기

모델 만들기

models.py (테이블[모델] 생성하기)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from django.contrib.auth.models import User

class Lone(models.Model):
    choice = (
        ('대출완료','대출완료'),
        ('회수중','회수중'),
        ('회수완료','회수완료'),
    )
    user_id = models.ForeignKey(User, on_delete=True)
    attention = models.CharField(max_length=10, choices=choice, default='대출완료')
    price = models.FloatField()

class Payback(models.Model):
    lone_id = models.ForeignKey(Lone, on_delete=True)
    payback = models.FloatField()

대출회수에 대한 테이블을 예시로 만들어서 해보도록하겠습니다.

  • 대출 테이블에 대한 필드
    • ID (PrimaryKey)
    • 사용자 ID (ForeignKey)
    • 상태 (대출완료, 회수중, 회수완료)
    • 대출금
  • 회수 테이블에 대한 필드
    • ID (PrimaryKey)
    • 대출모델 ID (ForeignKey)
    • 회수금

대출금회수금을 비교해서 대출 테이블의 상태를 업데이트하는 로직을 구현하려고 합니다!!!

pre_save 함수 만들기

models.py (pre_save 함수)

1
2
3
4
5
6
7
8
9
10
11
12
13
...
def attention_pre_save(sender, instance, *args, **kwargs):
    qs = Lone.objects.get(pk=Payback.lone_id.id)
    ## 대출금과 회수금이 같을 시 "회수완료"
    if int(qs.price) == int(instance.payback):
        qs.attention = '회수완료'
        qs.save()
    ## 회수금이 0보다 클 시 "회수중"
    elif int(instance.payback) > 0:
        qs.attention = '회수중'
        qs.save()

pre_save.connect(attention_pre_save, sender=Payback)

이렇게 하면 대출금회수금에 차이에 따라 상태값이 자동으로 저장되는 테이블이 만들어집니다. 여기서 추가로 해야할 사항은 여러번 나눠서 회수를 할 경우를 위해 회수금의 총합대출금에 따른 상태값 저장이 되는 pre_save 함수를 만들어 보겠습니다.

추가 사항

models.py (회수의 총합 추가)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
def attention_pre_save(sender, instance, *args, **kwargs):
    qs = Lone.objects.get(pk=Payback.lone_id.id)
    total_list = Payback.objects.filter(lone_id=instance.lone_id).values_list('payback')
    ## 회수금의 총합에 대한 로직
    total = 0
    for i in total_list:
    	total = total+int(i[0])
    ## 대출금과 total에 현재 저장할 payback을 더한 값이 같을 시 "회수완료"
    if int(qs.price) == total+instance.payback:
        qs.attention = '회수완료'
        qs.save()
    ## total에 현재 저장할 payback을 더한 값이 0보다 클 시 "회수중"
    elif total+instance.payback > 0:
        qs.attention = '회수중'
        qs.save()

pre_save.connect(attention_pre_save, sender=Payback)

objects.values_list라는 명령어로 payback필드의 값들을 리스트 형태로 불러와서 반복문으로 총합을 구해 계산했습니다. 여기서 주의할 점은 대출과 회수는 1대 다의 관계임으로 대출ID에 해당하는 회수금의 합을 구해야 헙니다. 저는 filter를 통해 대출ID에 해당되는 회수 모델의 정보 중 회수금의 합을 구했습니다.

models.py (회수총액이 대출금을 초과시 에러발생)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
class Payback(models.Model):
    lone_id = models.ForeignKey(Lone)
    payback = models.FloatField()

    def clean(self):
        qs = Lone.objects.get(pk=self.lone_id.id)
        total_list = Payback.objects.filter(lone_id=self.lone_id).values_list('payback')
        ## 회수금의 총합에 대한 로직
        total = 0
        for i in total_list:
            otal = total+int(i[0])
        if qs.price < total+self.payback:
            raise ValidationError("회수총액이 대출금을 초과할 수 없습니다.")

테이터를 Create 시 오류를 발생시키는 함수에서도, pre_save 함수와 동일한 로직으로 오류 검출을 하였습니다.