Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AttributeError when a ParentalKey related manager is used as the queryset for a ModelChoiceField #160

Open
bcdickinson opened this issue Apr 8, 2022 · 3 comments

Comments

@bcdickinson
Copy link

bcdickinson commented Apr 8, 2022

Bug

FakeQuerySet doesn't have a _prefetch_related_lookups member, so Django throws an attribute error when using it as the queryset kwarg to a ModelChoiceField, here: https://github.com/django/django/blob/3.2.12/django/forms/models.py#L1167

My guess at a solution at this moment in time is to just add _prefetch_related_lookups = () to FakeQuerySet.__init__(), but I'm not 100% sure that's the right answer.

Context

I'm creating a QuestionPage that has multiple choice questions on it. QuestionPages have many Questions which in turn have many Answers. I generate a Form to use on the page and that works fine, but it breaks when I'm previewing the page with the following error:

'FakeQuerySet' object has no attribute '_prefetch_related_lookups'

Here's a sketch:

class QuestionPage(Page):
  ...
  
  content_panels = [
    ...,
    InlinePanel('questions'),
  ]


class Question(ClusterableModel):
  question_page = ParentalKey(QuestionPage, related_name='questions')
  ...

  panels  = [
    InlinePanel('answers'),
    ...
  ]
  

class Answer(models.Model):
  question = ParentalKey(Question, related_name="answers")
  ...


class QuestionPageForm(forms.Form):
  def __init__(self, *args, question_page: QuestionPage, **kwargs):
    super().__init__(*args, **kwargs)

    for question in question_page.questions.all():
      self.fields[f"question-{question.pk}"] = forms.ModelChoiceField(
        queryset=question.answers.all(),  # This seems to be what causes the AttributeError during previews
      )
@bcdickinson
Copy link
Author

While working around this in my project, I found that we're missing FakeQuerySet.iterator() too. Here's my hack du jour that seems to be working nicely for the time being:

def monkey_patch_fakequeryset():
    FakeQuerySet._prefetch_related_lookups = ()

    def fakequeryset_iterator(self):
        return self

    FakeQuerySet.iterator = fakequeryset_iterator


monkey_patch_fakequeryset()

@wimfeijen
Copy link

wimfeijen commented Apr 28, 2022

Hi, I just wanted to say that I got the same error, and the proposal by bcdickinson seems to be a good one!

I am using the latest version of Wagtail 2.16.2, Django 3.2.13 and getting this error when previewing certain wagtailpages which contain ClusterableModels and ParentalManyToManyFields:
'FakeQuerySet' object has no attribute '_prefetch_related_lookups'

@wimfeijen
Copy link

Hi, I created a patch: #163

It only adds a _prefetch_related_lookups objects. I did not add an iterator because I did not run into that bug (and couldn't test)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants