programing

Django Unique Together (외래 키 포함)

nasanasas 2020. 12. 25. 10:05
반응형

Django Unique Together (외래 키 포함)


메타 옵션 unique_together을 사용하여 특정 규칙을 적용 하려는 상황이 있습니다 . 다음은 중개 모델입니다.

class UserProfileExtension(models.Model):
    extension = models.ForeignKey(Extension, unique=False)
    userprofile = models.ForeignKey(UserProfile, unique=False)
    user = models.ForeignKey(User, unique=False)  

    class Meta:
        unique_together = (("userprofile", "extension"),
                           ("user", "extension"),
                           # How can I enforce UserProfile's Client 
                           # and Extension to be unique? This obviously
                           # doesn't work, but is this idea possible without
                           # creating another FK in my intermediary model 
                           ("userprofile__client", "extension"))

다음은 UserProfile입니다.

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    client = models.ForeignKey(Client)

감사.


당신은 할 수 없습니다.

unique_together절은 직접 변환됩니다 SQL고유 인덱스. 여러 테이블의 조합이 아닌 단일 테이블의 열에 만 설정할 수 있습니다.

그래도 직접 유효성 검사를 추가 할 수 있습니다. validate_unique메서드 를 덮어 쓰고이 유효성 검사를 추가하면됩니다.

문서 : http://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.validate_unique


내 해결책은 Django의 get_or_create 를 사용하는 입니다. get_or_create를 사용하면 행이 이미 데이터베이스에 존재하면 쓸모없는 get이 발생하고 존재하지 않으면 행이 생성됩니다.

예:

 
extension = Extension.objects.get(pk=someExtensionPK)
userProfile = UserProfile.objects.get(pk=someUserProfilePK)
UserProfileExtension.objects.get_or_create(extension=extension, userprofile=userProfile)

내 2 센트, @Wolph의 수락 된 응답 보완

하지만 유효성 검사를 직접 추가 할 수 있습니다. 간단히 validate_unique 메서드를 덮어 쓰고이 유효성 검사를 추가하면됩니다.

이것은 누군가가 유용하게 사용할 수있는 작동하는 예제 코드입니다.

from django.core.exceptions import ValidationError


class MyModel(models.Model):

    fk = models.ForeignKey(AnotherModel, on_delete=models.CASCADE)

    my_field = models.CharField(...)  # whatever

    def validate_unique(self, *args, **kwargs):
        super(MyModel, self).validate_unique(*args, **kwargs)

        if self.__class__.objects.\
                filter(fk=self.fk, my_field=self.my_field).\
                exists():
            raise ValidationError(
                message='MyModel with this (fk, my_field) already exists.',
                code='unique_together',
            )

django 2.2 이상 버전에서는 제약 조건 및 인덱스를 모델 클래스 메타 옵션으로 사용하는 것이 좋습니다.

https://docs.djangoproject.com/en/2.2/ref/models/options/#django.db.models.Options.unique_together

https://docs.djangoproject.com/en/2.2/ref/models/options/#django.db.models.Options.constraints


You need to call Models.full_clean() method to call validate_unique for foreignKey. You can override save() to call this

class UserProfileExtension(models.Model):
    extension = models.ForeignKey(Extension, unique=False)
    userprofile = models.ForeignKey(UserProfile, unique=False)
    user = models.ForeignKey(User, unique=False)  


    def save(self, *args, **kwargs):
        self.full_clean()
        super().save(*args, **kwargs)

    class Meta:
        unique_together = (("userprofile", "extension"),
                       ("user", "extension"),
                       # How can I enforce UserProfile's Client 
                       # and Extension to be unique? This obviously
                       # doesn't work, but is this idea possible without
                       # creating another FK in my intermediary model 
                       ("userprofile__client", "extension"))

ReferenceURL : https://stackoverflow.com/questions/4440010/django-unique-together-with-foreign-keys

반응형