나는 그 자체와 다 대다 관계를 가진 모델을 가지고있다.django 모델의 루프 감지
그룹이 자신의 하위 그룹 또는 하위 그룹의 하위 그룹 등이되지 못하게하는 모델에 대한 유효성 검사를 만들고 싶습니다. 그 목적은 루프/무한 재귀.
다음과 같이 model clean() 메서드에서 구현하려고 시도했습니다.
또한 트랜잭션을 사용하여 save() 모델 모델에서이 구현을 시도했습니다.
두 경우 모두 유효하지 않은 변경 사항이 (잘못) 데이터베이스에 저장되는 상황이 발생했으나 두 인스턴스 중 하나를 추가로 변경하려고하면 유효성 검사에서 오류를 감지하지만 그 시점에서 , 잘못된 데이터가 이미 데이터베이스에 있습니다.
이것이 가능한지 궁금한 데요, 그렇다면 모델 유효성 검사에서 가능하면 내 팀의 모든 사람들이 작성한 모든 양식에서이 유효성 검사를 호출하는 것을 기억하지 않아도됩니다. 미래. 지체없이
코드 :
class Group(models.Model):
name = models.CharField(max_length=200)
sub_groups = models.ManyToManyField('self', through='SubGroup', symmetrical=False)
def validate_no_group_loops(self, seen=None):
if seen is None:
seen = []
if self.id in seen:
raise ValidationError("LOOP DETECTED")
seen.append(self.id)
for sub_group in self.target.all():
sub_group.target.validate_no_group_loops(seen)
# I thought I would use the standard validation mechanism in the clean()
# method, but it appears that when I recurse back to the group I started
# with, I do so with a query to the database which retreives the data before
# it's been modified. I'm still not 100% sure if this is the case, but
# regardless, it does not work.
def clean(self):
self.validate_no_group_loops()
# Suspecting that the problem with implementing this in clean() was that
# I wasn't testing the data with the pending modifications due to the
# repeated queries to the database, I thought that I could handle the
# validation in save(), let the save actually put the bad data into the
# database, and then roll back the transaction if I detect a problem.
# This also doesn't work.
def save(self, *args, **kwargs):
super(Group, self).save(*args, **kwargs)
try:
self.validate_no_group_loops()
except ValidationError as e:
transaction.rollback()
raise e
else:
transaction.commit()
class SubGroup(models.Model):
VERBS = { '+': '+', '-': '-' }
action = models.CharField(max_length=1, choices=VERBS.items(), default='+')
source = models.ForeignKey('Group', related_name='target')
target = models.ForeignKey('Group', related_name='source')
감사에 앞서 당신이 제공 할 수있는 지원 시간.
[편집] FYI, 트랜잭션 관리에 사용하는 메커니즘을 기반으로 말할 수 없다면 현재 RHEL6 용 페도라 EPEL 저장소에서 사용할 수있는 장황한 1.2를 사용하고 있습니다. 솔루션을 사용할 수 있지만 1.3으로 업그레이드해야하는 경우 업그레이드해도 문제가 없습니다. 또한 Red Hat에서 RHEL6에서 사용할 수있는 Python 2.6.6을 사용하고 있습니다. 차라리 파이썬 업그레이드를 피하고 싶지만 관련성이 높은지 의심 스럽다.
왜 다 대다 관계를 사용하는지 설명해 주실 수 있습니까? 구조와 같은 트리가 있고이 패턴을 사용합니다.이 노드가 비어 있으면 모든 노드에 "부모"특성이 있습니다. 루트 노드입니다. 또는 https://github.com/django-mptt/django-mptt/ – guettli
을 사용할 수 있습니다. 내 응용 프로그램에서는 나무가 아닙니다. 그룹이 다른 많은 그룹에 포함될 수도 있고, 그룹이 여러 그룹을 포함 할 수도 있습니다. 이것은 관련없는 코드가 많은 사람들에게 부담을주지 않으면 서 문제를 표현하는 응용 프로그램의 간소화 된 버전이기 때문에 하위 그룹 관계에 대한 매개 변수를 정의하기위한 통과 모델이 필요합니다. – mkomitee
[내 질문] (http://stackoverflow.com/questions/5795742/django-mptt)에 링크 된 [django_dag] (https://github.com/elpaso/django-dag) 프로젝트를 보면 - 그리고 - parents-parents), models.py 라인 195에는'circular_checker'라는 이름의'@ staticmethod'가 있음을 알 수 있습니다. 코드에서 영감을 얻을 수 있습니다. –