{{{
class ReviewsModelManager(models.Manager):
def get_queryset(self):
qs = super().get_queryset()
qs = qs.filter(published=True)
return qs
def get_full_queryset(self):
qs = super().get_queryset()
return qs
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
objects = BaseModelManager()
class BookReview(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE,
related_name='reviews')
content = models.CharField(max_length=255)
published = models.BooleanField(default=False)
objects = ReviewsModelManager()
}}}
The concept is that we are having one book that could have multiple
reviews. A review could be published or not. We then apply a model manager
to show only published book reviews. We keep the original queryset to use
in the admin later in the `get_full_queryset`
Then we add a model admin in admin.py like so:
{{{
class ReviewTabularInline(admin.TabularInline):
def get_queryset(self, request):
qs = self.model._default_manager.get_full_queryset()
ordering = self.get_ordering(request)
if ordering:
qs = qs.order_by(*ordering)
return qs
class BookAdmin(admin.ModelAdmin):
inlines = [ReviewTabularInline]
def get_queryset(self, request):
qs = self.model._default_manager.get_full_queryset()
ordering = self.get_ordering(request)
if ordering:
qs = qs.order_by(*ordering)
return qs
}}}
Default querysets are hijacked in both admin and inline in order to
include all reviews - both published and not.
If you go to the `book admin`, the inline will display all reviews as it
should.
If you try to mark a review from `published` to `not published` in the
inline this will also work.
But if you try to mark `not-published` to `published` that is failing
with an unspecified error.
The reason for this is that the inline form does not validate.
Validation fails because the inline form receives an extra field /called
`id` by default or whatever the PK name for the model is/
That field is a `ModelChoiceField`.
But the queryset for that `ModelChoiceField` is done with the
`get_queryset` of the custom model manager - `ReviewsModelManager` that
will not include items that are not marked as `not-published`. Since you
are trying to update `non-published` to `published`, that object is going
to be missing in `ModelChoiceField` queryset which causes the field not to
validate and that drops the whole form.
This inconsistency. `ModelChoiceField` `id` field should also get the
queryset that is specified in the inline's `get_queryset`
--
Ticket URL: <https://code.djangoproject.com/ticket/33813>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.