A ordem do gerente nos modelos Django é importante!

Às vezes, quero incorporar algum tipo de controle de visibilidade para modelos.

class MyModel(models.Model):
# ... all the fields are here

ACTIVE
='active'
INACTIVE
='inactive'

STATUS_CHOICES
= (
(ACTIVE, 'Active'),
(INACTIVE, 'Inactive'),
)

status
= models.CharField(max_length=255, choices=STATUS_CHOICES, db_index=True)

Freqüentemente, esse requisito é introduzido depois que muitas visualizações e lógicas foram escritas, então é uma dor real ter que atualizar muitas consultas de MyModel.objects.all()paraMyModel.objects.filter(status='active')

A solução é criar um gerenciador para lidar com isso, mas eu ainda quero ser capaz de fazer referência a instâncias com o status ‘inativo’ de alguma forma, então incluirei uma referência ao Django Manager padrão:

class MyManager(models.Manager):
def get_query_set(self):
return super(MyManager, self).get_query_set().filter(status=MyModel.ACTIVE)

class MyModel:
# other stuff goes here

unfiltered
= models.Manager()
objects
= MyManager()

Aqui, encontrei um problema. Definir um simples ListViewpara este modelo mostrará todos os modelos, independentemente de seus statusatributos!

class MyListView(ListView):
model
= MyModel

Eu começo a me aprofundar no código-fonte do Django e descobri que o ListViewusa um _default_manageratributo para buscar o queryset. Acontece que este _default_manageratributo é preenchido usando o primeiro gerenciador definido no modelo!

Portanto, inverter os gerentes resolve nosso problema com ListView:

class MyModel:
# other stuff goes here

objects
= MyManager()
unfiltered
= models.Manager()

Porém, ainda há um problema. Se você usar o aplicativo Django Admin para administrar seu modelo, não verá nenhum modelo com o status ‘inativo’. A solução é simples, você simplesmente sobrescreve o método `get_queryset ’em sua classe de administração:

class MyModelAdmin(admin.ModelAdmin):
def queryset (self, request):
qs
= MyModel.unfiltered.all()
ordering
= self.get_ordering(request)
if ordering:
qs
= qs.order_by(*ordering)
return qs

É uma pena que não haja gancho ModelAdminpara lidar com a parte do pedido, mas é a vida.

Portanto, se você tiver muito código dependendo do uso MyModel.objects.filter(), essa é uma maneira relativamente fácil de fornecer filtragem padrão de seus dados sem alterar muito código.