【问题标题】:django channel image serializing error says You cannot call this from an async context - use a thread or sync_to_asyncdjango 通道图像序列化错误说您不能从异步上下文中调用它 - 使用线程或 sync_to_async
【发布时间】:2022-11-27 05:14:32
【问题描述】:

我有一个发票序列化器,其中包括一个图像序列化器,因为发票与图像具有一对多关系

当我在发票序列化程序的图像字段中启用 many=True 时出现此错误

Exception inside application: You cannot call this from an async context - use a thread or sync_to_async.
Traceback (most recent call last):
  File "D:\projects\TaxiTR\env\lib\site-packages\django\contrib\staticfiles\handlers.py", line 101, in __call__
    return await self.application(scope, receive, send)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\routing.py", line 62, in __call__
    return await application(scope, receive, send)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\security\websocket.py", line 37, in __call__
    return await self.application(scope, receive, send)
  File "D:\projects\TaxiTR\core\middleware.py", line 57, in __call__
    return await super().__call__(scope, receive, send)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\middleware.py", line 24, in __call__
    return await self.inner(scope, receive, send)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\sessions.py", line 47, in __call__
    return await self.inner(dict(scope, cookies=cookies), receive, send)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\sessions.py", line 263, in __call__
    return await self.inner(wrapper.scope, receive, wrapper.send)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\auth.py", line 185, in __call__
    return await super().__call__(scope, receive, send)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\middleware.py", line 24, in __call__
    return await self.inner(scope, receive, send)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\routing.py", line 116, in __call__
    return await application(
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\consumer.py", line 94, in app
    return await consumer(scope, receive, send)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\consumer.py", line 58, in __call__
    await await_many_dispatch(
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\utils.py", line 50, in await_many_dispatch
    await dispatch(result)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\consumer.py", line 73, in dispatch
    await handler(message)
  File "D:\projects\TaxiTR\env\lib\site-packages\channels\generic\websocket.py", line 173, in websocket_connect
    await self.connect()
  File "D:\projects\TaxiTR\ride\consumers.py", line 62, in connect
    shift = await self.get_active_shift()
  File "D:\projects\TaxiTR\ride\consumers.py", line 179, in get_active_shift
    shift_data = ShiftDetailSerializer(shift).data
  File "D:\projects\TaxiTR\env\lib\site-packages\rest_framework\serializers.py", line 555, in data
    ret = super().data
  File "D:\projects\TaxiTR\env\lib\site-packages\rest_framework\serializers.py", line 253, in data
    self._data = self.to_representation(self.instance)
  File "D:\projects\TaxiTR\env\lib\site-packages\rest_framework\serializers.py", line 522, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "D:\projects\TaxiTR\env\lib\site-packages\rest_framework\serializers.py", line 686, in to_representation
    return [
  File "D:\projects\TaxiTR\env\lib\site-packages\rest_framework\serializers.py", line 687, in <listcomp>
    self.child.to_representation(item) for item in iterable
  File "D:\projects\TaxiTR\env\lib\site-packages\rest_framework\serializers.py", line 522, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "D:\projects\TaxiTR\env\lib\site-packages\rest_framework\serializers.py", line 522, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "D:\projects\TaxiTR\env\lib\site-packages\rest_framework\relations.py", line 542, in to_representation
    return [
  File "D:\projects\TaxiTR\env\lib\site-packages\django\db\models\query.py", line 394, in __iter__
    self._fetch_all()
  File "D:\projects\TaxiTR\env\lib\site-packages\django\db\models\query.py", line 1866, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "D:\projects\TaxiTR\env\lib\site-packages\django\db\models\query.py", line 87, in __iter__
    results = compiler.execute_sql(
  File "D:\projects\TaxiTR\env\lib\site-packages\django\db\models\sql\compiler.py", line 1393, in execute_sql
    cursor = self.connection.cursor()
  File "D:\projects\TaxiTR\env\lib\site-packages\django\utils\asyncio.py", line 24, in inner
    raise SynchronousOnlyOperation(message)
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.

但如果 many=False 它工作正常 我的模特:

`class Invoice(models.Model):
    class PaymentMethod(models.TextChoices):
        CASH = "CASH", _("Cash")
        CREDIT = "CREDIT", _("Credit")
        CONTRACT = "CONTRACT", _("Contract")
    tips = models.FloatField(default=0, blank=True, null=True)
    price = models.FloatField(default=0, blank=True, null=True)
    expected_price = models.FloatField(default=0, blank=True, null=True)
    passenger = models.CharField(max_length=100, blank=True, null=True)
    client = models.IntegerField(blank=True, null=True)

    payment_method = models.CharField(
        max_length=50, choices=PaymentMethod.choices)
`

`
class Image(models.Model):
    invoice = models.ForeignKey(
        "invoices.Invoice", on_delete=models.CASCADE, related_name="images")
    image = models.ImageField(upload_to=documents_path)
`

序列化程序:

`class ImageSerializer(serializers.ModelSerializer):
    image = serializers.ImageField(required=False)

    class Meta:
        model = Image
        fields = ['image']


class InvoiceSerializer(serializers.ModelSerializer):
    total_earnings = serializers.ReadOnlyField()
    net = serializers.ReadOnlyField()
    qst = serializers.ReadOnlyField()
    gst = serializers.ReadOnlyField()
    revendence = serializers.ReadOnlyField()
    images = ImageSerializer(many=True, required=False)

    class Meta:
        model = Invoice
        fields = [
            "tips",
            "price",
            "passenger",
            "client",
            "total_earnings",
            "net",
            "qst",
            "gst",
            "revendence",
            "images",
            "id",
        ]
        read_only_fields = ['id', ]

  def create(self, validated_data):
        images_data = self.context.get('request').FILES.getlist('images', None)
        validated_data.pop('images', None)

        invoice = Invoice.objects.create(**validated_data)
        for image in images_data:
            Image.objects.create(image=image, invoice=invoice)
        return invoice

    def update(self, instance, validated_data):
        images_data = self.context.get('request').FILES.getlist('images', None)
        if images_data:

            instance.images.all().delete()
            invoice_docs = [
                Image(invoice=instance, image=image) for image in images_data
            ]
            Image.objects.bulk_create(
                invoice_docs
            )
        return super().update(instance, validated_data)



`

在我的应用程序中,我有很多序列化器有一个字段引用另一个序列化器,其中许多 = True 并且工作正常但在这个它给了我这个错误,我搜索了错误但没有找到任何像我这样的问题所以我希望有人可以帮助

【问题讨论】:

    标签: django asynchronous serialization django-rest-framework django-channels


    【解决方案1】:

    问题是因为当访问 invoice.images 时运行一个新的同步数据库查询所以我编辑了我的发票管理器以在获取任何发票时预取图像

     class InvoiceManager(Manager):
        def get_queryset(self):
            return super().get_queryset().prefetch_related('images')
    

    【讨论】:

      猜你喜欢
      • 2020-09-07
      • 2021-12-23
      • 2023-03-03
      • 2023-01-27
      • 2021-10-23
      • 2020-12-20
      • 1970-01-01
      • 2012-08-22
      • 1970-01-01
      相关资源
      最近更新 更多