django 注解Many2Many链接工作,但仅适用于SQLite(测试)而不是MariaDB(生产)

f2uvfpb9  于 2023-06-25  发布在  Go
关注(0)|答案(1)|浏览(77)

我正在尝试注解一个包含many2many字段的模型:

class Link(models.Model):
    products = models.ManyToManyField(Product, related_name = "%(class)s_name", related_query_name = "product_link_qs", blank = True)
    position = models.ForeignKey(Position, on_delete = models.CASCADE)

class Position(models.Model):
    place = models.PositiveIntegerField(unique = True) 
    store = models.ForeignKey(Store, on_delete = models.CASCADE)

class Store(models.Model):
    name = models.CharField("name", max_length = 32)

在我的管理中,我使用annotate()来耦合信息:

@admin.register(Link)
class LinkAdmin(admin.ModelAdmin):
    list_display = ["product", "get_store"]
    list_filter = ["position__store"]

    ### extend by product_link_qs related name property to make field sortable in the admin
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.annotate(storename = Product.objects.filter(product_link_qs = OuterRef("id")).values("store__name"))

    @admin.display(description = "store name", ordering = "storename")
    def get_store(self, obj):
        return obj.storename or None

一个职位只关联一个产品:

这在SQLite的测试和MariaDB的生产中运行得非常好

在链接中添加第二个产品:

SQLite上测试,但给出:django.db.utils.OperationalError:(1242,'Subquery returns more than 1 row') onMariaDB

cu6pst1q

cu6pst1q1#

最简单的方法可能是用商店的名称来注解它:

from django.db.models import F

@admin.register(Link)
class LinkAdmin(admin.ModelAdmin):
    list_display = ['product', 'get_store']
    list_filter = ['position__store']

    ### extend by product_link_qs related name property to make field sortable in the admin
    def get_queryset(self, *args, **kwargs):
        return (
            super()
            .get_queryset(*args, **kwargs)
            .annotate(storename=F('products__store__name'))
            .distinct()
        )

    @admin.display(description='store name', ordering='storename')
    def get_store(self, obj):
        return obj.storename or None

相关问题