#33813: Incorrect querysets for InlineModels for django.cotrib.admin -------------------------------------+------------------------------------- Reporter: Hristo | Owner: nobody Trendafilov | Type: Bug | Status: new Component: | Version: contrib.admin | Keywords: Severity: Normal | admin,inlines,custom model manager Triage Stage: | Has patch: 0 Unreviewed | Needs documentation: 0 | Needs tests: 0 Patch needs improvement: 0 | Easy pickings: 0 UI/UX: 0 | -------------------------------------+------------------------------------- Hello. I have run into the following that is applicable to all Django versions. Let's have two models and one is using a custom model manager like so
{{{ 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. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/01070181aec393de-2a9f1c9f-908a-464b-a99e-aced7436a55c-000000%40eu-central-1.amazonses.com.