#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.

Reply via email to