À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 ListView
para este modelo mostrará todos os modelos, independentemente de seus status
atributos!
class MyListView(ListView):
model = MyModel
Eu começo a me aprofundar no código-fonte do Django e descobri que o ListView
usa um _default_manager
atributo para buscar o queryset. Acontece que este _default_manager
atributo é 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 ModelAdmin
para 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.