#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 [email protected].
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.

Reply via email to