ManyToMany字段默认选择所有模型实例/更改默认的get_queryset

时间:2018-10-28 09:38:05

标签: python django django-models

我更改了.all方法,因此它将仅选择具有published=True的实例:

class EventManager(models.Manager):
    def all(self, *args, **kwargs):
        return super().get_queryset().filter(published=True, *args, **kwargs)

这与问题模型字段有关:

class Event(models.Model):
    related_events = models.ManyToManyField('self', blank=True, related_name='related')
    published = models.BooleanField(default=False)
    objects = EventManager()

结果,ManyToManyField最终选择了所有Event实例。 您建议我做什么以保存published功能并能够手动添加相关事件?谢谢。

2 个答案:

答案 0 :(得分:1)

据我所知,Django并不使用Model.objects作为管理器,而使用Model._basemanager作为管理器,通常应该返回所有对象。

您可以在此处使用limit_choices_to [Django-doc]来限制多对多字段的选择,例如:

from django.db.models import Q

class Event(models.Model):
    related_events = models.ManyToManyField(
        'self',
        limit_choices_to=Q(published=True)
        blank=False,
        related_name='related'
    )
    published = models.BooleanField(default=False)
    objects = EventManager()

您可能还希望删除blank=True,因为这意味着默认情况下,您使该字段不显示在表单中的op。因此,如果您想手动编辑相关事件,那么blank=False

此外,默认情况下,ManyToManyField'self'符号。因此,这意味着如果event1related_events的{​​{1}}中,那么event2也在event2的{​​{1}}中。如果您不想这样做,则可能要添加symmetrical=False [Django-doc]

请注意,在某些情况下,未发布的事件可能会在相关事件中结束。例如,通过将已发布事件添加到相关事件,然后“取消发布”它。

对于经理,我认为您最好修补related_events方法:

event1

否则,有很多方法可以get_queryset规避”。例如:class EventManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(published=True)仍然会给我 all filter个字,但是由于我没有致电Event.objects.filter(id__gt=-1),因此不会对发布内容进行过滤。

Event中,您可以尝试为此.all()指定查询集:

ModelAdmin

答案 1 :(得分:1)

这就是我最终要做的,目的是仅在html中显示已发布的事件,并在管理控制台中显示所有事件(已发布和未发布)。

class EventManager(models.Manager):
"""
changing get_queryset() to show only published events.
if all is set to True it will show both published and unpublished
if False, which is default it will show only published ones
"""
    def get_queryset(self, all=False):
        if not all:
            return super().get_queryset().filter(published=True)
        else:
            return super().get_queryset()

class Event(models.Model):
    related_events = models.ManyToManyField('self', blank=True, related_name='related')
    published = models.BooleanField(default=False)
    objects = EventManager()

然后在ModelAdmin中,我将get_queryset设置为all的情况下调用True,否则我将看不到未发布的内容。

class EventAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        return Event.objects.get_queryset(all=True)

我不能简单地更改模型的all方法,因为它会通过向其添加所有模型实例而与我的ManyToManyField混在一起。所以我做了所有这一切。