【问题标题】:Django: 'Q' object is not iterableDjango:'Q'对象不可迭代
【发布时间】:2021-07-04 03:09:47
【问题描述】:

我有以下 APIView:

class SubmitFormAPIView(APIView):
    def put(self, request, pk):
        # some other codes
        
        form = Form.objects.get(id=pk)
        tu_filter, target_user = self._validate_target_user(request, form)
        user_status, created = UserFormStatus.objects.get_or_create(
            tu_filter,
            form_id=pk,
            user_id=request.user.pk
        )

        # Some other codes.
    
    def _validate_target_user(request, form):
        if some_conditions:
            return Q(), None
        else:
            try:
                target_user_id = int(request.GET.get('target_user_id))
            except ValueError:
                raise ValidationError()

            target_user = get_user_model().objects.get(id=target_user_id)
            return Q(target_user_id=target_user_id), target_user

但是当 django 想要执行 get_or_create 方法时,会引发以下错误:

TypeError: 'Q' object is not iterable

注意:如果_validate_target_user() 返回Q(), None,则不会引发错误并且视图可以正常工作。返回return Q(target_user_id=target_user_id), target_user 时将引发错误。

我知道,问题信息没有填写,我只是想知道,这个错误是什么原因造成的?

【问题讨论】:

    标签: django django-models django-orm django-q


    【解决方案1】:

    来源get_or_create(...)

    def get_or_create(self, <b>defaults=None, **kwargs</b>):
    这表明 get_or_create(...) 不接受任何 args 不像 get()filter(...) 方法。 由于您正在执行如下函数,Python 认为 tu_filterdefault 参数的值,预计该参数是可迭代的。
    get_or_create(
                tu_filter,
                form_id=pk,
                user_id=request.user.pk
            )

    【讨论】:

      【解决方案2】:

      除了返回 Q 对象之外,您还可以只传递一个过滤器字典,例如

      { 'target_user_id': target_user_id }
      

      您可以使用**tu_filter 作为参数运行get_or_create,而无需Q

      class SubmitFormAPIView(APIView):
          def put(self, request, pk):
              # some other codes
              
              form = Form.objects.get(id=pk)
              tu_filter, target_user = self._validate_target_user(request, form)
              user_status, created = UserFormStatus.objects.get_or_create(
                  **tu_filter,
                  form_id=pk,
                  user_id=request.user.pk
              )
      
              # Some other codes.
          
          def _validate_target_user(request, form):
              if some_conditions:
                  return {}, None
              else:
                  try:
                      target_user_id = int(request.GET.get('target_user_id))
                  except ValueError:
                      raise ValidationError()
      
                  target_user = get_user_model().objects.get(id=target_user_id)
                  return { 'target_user_id': target_user_id }, target_user
      

      编辑:至于导致错误的原因,我的猜测是 Django 不清楚使用 Q 作为 get_or_create 语句的一部分,因为它不知道如何处理它以防对象需要创建的。因此,更好的方法是:

      UserFormStats.objects.filter(tu_filter).get_or_create(form_id=pk, user_id=request.user.pk)
      

      【讨论】:

      • 是的,你猜对了。 get_or_create() 不能接受 Q()
      猜你喜欢
      • 2021-02-04
      • 2020-02-28
      • 2013-05-07
      • 2019-07-25
      • 1970-01-01
      • 1970-01-01
      • 2020-05-25
      • 2021-06-09
      • 2019-10-15
      相关资源
      最近更新 更多