Django UniqueConstraint 不适用于 ManyToManyField,出现异常 FieldDoesNotExist

Django UniqueConstraint doesn't works with ManyToManyField, got exception FieldDoesNotExist

Shopuser 之间的 ForeignKey 切换到 ManyToManyField 时,迁移停止工作。我希望商店能够同时由不同的用户拥有:

class Shop(models.Model):
    name = models.CharField('name', max_length=120)
    #user = models.ForeignKey(User, on_delete=models.CASCADE)   ##before
    shopuser= models.ManyToManyField(User, related_name="shopusers", blank=True)    ##after

    class Meta:
        constraints = [models.UniqueConstraint(fields=['shopuser', 'name'], name='user cant have the same shop twice!')] 
    
    ## after:
    @property
    def get_shopuser(self):
        return ", ".join([u.username for u in self.shopuser.all()])

class Warehouse(models.Model):
    address = models.CharField('address', max_length=120)
    user = models.ManyToManyField(User, related_name="User", blank=True)

django.core.exceptions.FieldDoesNotExist: NewShop has no field named 'shopusers'

我想通过选择一个相关的名称我可以对 User 模型使用多个关系?我已经尝试 完全删除我的数据库(和迁移文件夹) 并从头开始迁移,但没有帮助:(

我调用代码的示例:

admin.py:

@admin.register(Shop)
class ShopAdmin(admin.ModelAdmin):
    list_display = ("name", "related_shopuser")
    list_filter = ("name", "shopuser")
    fieldsets = [("Requrired Information", {"description": "These fields are required", 
                                            "fields": (("name", "shopuser"))}),]

    def related_shopuser(self, obj):
        return obj.get_shopuser

Djanog 迁移从哪里获得 FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))NewShop?它是从 ModelName Shop 自动生成的吗?

如果不需要(项目已经在生产中),请尝试删除您的迁移文件,或者至少删除第一次添加用户字段的迁移

问题

ManyToManyField 上的 UniqueConstraint 将无法按预期工作。如果你想强制约束,你应该定义一个中间模型 并使用 through--(Django doc) 参数连接它们。

为了简单起见,我假设您有如下模型,

class Shop(models.Model):
    name = models.CharField('name', max_length=120)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=[
                    'user',
                    'name'
                ],
                name='user cant have the same shop twice!'
            )
        ]

现在您想将 user 字段从 ForeignKey 变为 ManyToManyField

注意:我把字段名从[=14改成了user<b>s</b> =],这样比较合适

方法一:移除唯一约束

class Shop(models.Model):
    name = models.CharField('name', max_length=120)
    <b>users = models.ManyToManyField(User)</b>

现在,运行 makemigrationsmigrate 命令

方法二:使用中间模型

<b>class ShopUserIntermediateModel(models.Model):
    shop = models.ForeignKey('Shop', models.CASCADE)
    user = models.ForeignKey(User, models.CASCADE)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=[
                    'shop',
                    'user'
                ],
                name='user cant have the same shop twice!'
            )
        ]</b>


class Shop(models.Model):
    name = models.CharField('name', max_length=120)
    users = models.ManyToManyField(User, <b>through=ShopUserIntermediateModel</b>)