문제

는데 그것이 가능한(그리고,그렇다면,방법)를 함께 체인의 여러 매니저를 생성하는 쿼리를 설정에 의해 영향을 받는 모두의 개인 관리자입니다.나는 설명할 것이 특정 예에서 나는 작업:

나는 여러 추상적인 모델 클래스를 사용하는을 제공하는 작은,특정한 기능을 다른 모델이다.이러한 두 모델은 DeleteMixin 및 GlobalMixin.

이 DeleteMixin 으로 정의한:

class DeleteMixin(models.Model):
    deleted = models.BooleanField(default=False)
    objects = DeleteManager()

    class Meta:
        abstract = True

    def delete(self):
        self.deleted = True
        self.save()

기본적으로 제공하는 의사를 삭제(는 삭제된 국기)대신 실제로 삭제한다.

이 GlobalMixin 으로 정의한:

class GlobalMixin(models.Model):
    is_global = models.BooleanField(default=True)

    objects = GlobalManager()

    class Meta:
        abstract = True

그것은 어떤 객체로 정의된 표시를 전체 또는 전용 개체(예:공개/개인 블로그 게시물).

모두의 이러한 자신의 관리자에 영향을 미치는 queryset 는 반환됩니다.내 DeleteManager 필터 queryset 만에 결과를 반환하는 삭제 깃발을 False 로 설정하는 동안,GlobalManager 필터 queryset 만 반환하는 결과가 표시되어 있습니다.여기에는 선언을 위한 두:

class DeleteManager(models.Manager):
    def get_query_set(self):
        return super(DeleteManager, self).get_query_set().filter(deleted=False)

class GlobalManager(models.Manager):
    def globals(self):
        return self.get_query_set().filter(is_global=1)

원하는 기능을 해야 하는 것 모델을 확장하 모두 이러한 추상적인 모델 및 수 있는 권한을 부여하여 만에 결과를 반환하는 다음을 포함하되 이에 국한되지 않는 삭제된 글로벌입니다.I ran 테스트 케이스 모델에 함께 4 인스턴스:하나의 글로벌 비 삭제는 하나의 글로벌하고 삭제되었 비 글로벌 비 삭제하고,하나는 비 글로벌하고 삭제됩니다.하려고 하면 결과를 얻을 설정합니다.SomeModel.체입니다.모든(),I get 인스턴스를 제 1 항 및 3(두 개의 비 삭제 된 것-great!).하려고 하면 어 SomeModel.체입니다.globals(),는 오류 메시지가 나 DeleteManager 없 globals(이것은 가정 내 모델을 선언은 이와 같:SomeModel(DeleteMixin,GlobalMixin).면 순서를 바꾸는지,나는 오류가 발생하지 않는 필터를 삭제한 것들).변경하는 경우 GlobalMixin 연결하 GlobalManager 하는 전역의 대체(그래서 새로운 명령이 될 것이 SomeModel.globals.globals()),난 경우 1 및 2(두 globals),동위한 결과를 얻을 인스턴스 1(세계 비 중 하나를 삭제).

나는 확실하지 않았다면 사람이 어떤 상황이 이와 유사한 온 것이었습니다.하나 그것을 만들 수 있는 방법에서 일 현재의 내 생각이나 재작업 기능을 제공하는 난 후에는 것이 매우 감사합니다.내가 이것을 알고 포스트는 약간의 장황한.면 더 이상의 설명이 필요를 제공합니다.

편집:

게시 궁극적인 솔루션을 사용하는 이 특정한 문제가 아래.그것은 링크를 기반으로 시몬의 사용자 정의 QuerySetManager.

도움이 되었습니까?

해결책

djangosnippets 에서이 스 니펫을 참조하십시오. http://djangosnippets.org/snippets/734/

사용자 정의 메소드를 관리자에 넣는 대신 쿼리 세트 자체를 서브 클래스합니다. 매우 쉽고 완벽하게 작동합니다. 내가 가진 유일한 문제는 모델 상속에 관한 것입니다. 쿼리 세트를 상속하더라도 모델 하위 클래스 ( "객체 = QuerySetManager ()"에서 항상 관리자를 정의해야합니다. QuerySetManager를 사용하면 더 의미가 있습니다.

다른 팁

다음은 Scott이 연결 한 Simon의 Custom QuerySetManager를 사용한 내 문제에 대한 특정 솔루션입니다.

from django.db import models
from django.contrib import admin
from django.db.models.query import QuerySet
from django.core.exceptions import FieldError

class MixinManager(models.Manager):    
    def get_query_set(self):
        try:
            return self.model.MixinQuerySet(self.model).filter(deleted=False)
        except FieldError:
            return self.model.MixinQuerySet(self.model)

class BaseMixin(models.Model):
    admin = models.Manager()
    objects = MixinManager()

    class MixinQuerySet(QuerySet):

        def globals(self):
            try:
                return self.filter(is_global=True)
            except FieldError:
                return self.all()

    class Meta:
        abstract = True

class DeleteMixin(BaseMixin):
    deleted = models.BooleanField(default=False)

    class Meta:
        abstract = True

    def delete(self):
        self.deleted = True
        self.save()

class GlobalMixin(BaseMixin):
    is_global = models.BooleanField(default=True)

    class Meta:
        abstract = True

쿼리 세트에 추가 기능을 추가하려는 미래의 모든 믹스 인은 단순히 Basemixin을 확장해야합니다 (또는 상속인 어딘가에 있음). 쿼리를 설정하는 것을 필터링하려고 할 때마다 필드가 실제로 존재하지 않는 경우 쿼리를 시도하는 경우 (즉, 해당 Mixin을 확장하지 않음) 시도 캐치로 랩했습니다. 글로벌 필터는 Globals ()를 사용하여 호출되며 삭제 필터가 자동으로 호출됩니다 (무언가가 삭제되면 표시하지 않기를 원합니다). 이 시스템을 사용하면 다음 유형의 명령이 가능합니다.

TemporaryModel.objects.all() # If extending DeleteMixin, no deleted instances are returned
TemporaryModel.objects.all().globals() # Filter out the private instances (non-global)
TemporaryModel.objects.filter(...) # Ditto about excluding deleteds

주목할만한 점은 삭제 필터가 관리자 인터페이스에 영향을 미치지 않는다는 것입니다. 기본 관리자가 먼저 선언되기 때문에 (기본값이됩니다). 관리자가 Model.Objects 대신 Model.Objects 대신 Model._Default_Manager를 사용하도록 변경했을 때를 기억하지 못하지만 삭제 된 인스턴스는 여전히 관리자에 표시됩니다 (삭제되지 않아야하는 경우).

내가 노력하는 동안 올을 구축하는 방법이 좋은 공장이지만,내가 실행되는 많은 문제로습니다.

최 것이 좋습니다 수 있습니 당신이 체인의 유산입니다.그것은 매우 일반적이,그래서 나는 확실하지 않다 그것이 얼마나 유용하지만,모든 당신이해야 할 것입니다:

class GlobalMixin(DeleteMixin):
    is_global = models.BooleanField(default=True)

    objects = GlobalManager()

    class Meta:
        abstract = True

class GlobalManager(DeleteManager):
    def globals(self):
        return self.get_query_set().filter(is_global=1)

당신이 원하는 무언가를 더 일반적인 가지고 올 수 있으로 정의하는 것입 base MixinManager 재정의 get_query_set() (당신만 원하는 이렇게 한 번;일을 매우 복잡해지지 않)및 그런 다음 전달의 목록을 필하고를 통해 추가 Mixins.

그것은 다음과 같이 보일 것이다(테스트에서 모든):

class DeleteMixin(models.Model):
    deleted = models.BooleanField(default=False)

    class Meta:
        abstract = True

def create_mixin(base_mixin, **kwargs):
    class wrapper(base_mixin):
        class Meta:
            abstract = True
    for k in kwargs.keys():
        setattr(wrapper, k, kwargs[k])
    return wrapper

class DeleteManager(models.Manager):
    def get_query_set(self):
        return super(DeleteManager, self).get_query_set().filter(deleted=False)

def create_manager(base_manager, **kwargs):
    class wrapper(base_manager):
        pass
    for k in kwargs.keys():
        setattr(wrapper, k, kwargs[k])
    return wrapper

Ok,그래서이긴 하지만,그것은 무엇을 얻는가?기본적으로,그것은 동일한 솔루션이지만,훨씬 더 많은 동적이고,좀 더 건조하지만,더 복잡한 읽을 수 있습니다.

첫 번째 만들자 동적으로:

def globals(inst):
    return inst.get_query_set().filter(is_global=1)

GlobalDeleteManager = create_manager(DeleteManager, globals=globals)

이 새로 생성 관리자의 서브 클래스 DeleteManager 고라는 방법 globals.

다음으로,당신은 만들의 믹스 인 모델:

GlobalDeleteMixin = create_mixin(DeleteMixin,
                                 is_global=models.BooleanField(default=False),
                                 objects = GlobalDeleteManager())

내가 말했듯이,그것이다.하지만 그것이 의미 없을 재정의 globals().당신이 원하는 경우 다른 타입의 관리자를 갖 globals(), 에,당신은 전화 create_manager 다시 다른 기초입니다.고로 추가할 수 있는 많은 새로운 방법으로 당신이 좋아한다.에 대해 동일한 관리자,당신은 단지 계속 추가하는 새로운 기능을 반환하는 다른 querysets.

그래서,이것이 정말로 실?어쩌면하지 않습니다.이 대답은 좀 더 운동 in(ab)의 사용하는 파이썬의 유연성을 제공합니다.내가 시도하지 않은 이것을 사용하지만,몇 가지를 사용의 기본 원칙의 동적으로 확장하는 클래스가 일을 쉽게 액세스할 수 있습니다.

알려주는 경우 아무것도 명확하고는 답변입니다.

고려해야 할 또 다른 옵션은 PassthroughManager입니다.

https://django-model-utils.readthedocs.org/en/latest/managers.html#passthroughmanager

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top