Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在Django REST Framework ModelSerializer的创建函数中使用field.set()?_Python_Django_Django Rest Framework - Fatal编程技术网

Python 如何在Django REST Framework ModelSerializer的创建函数中使用field.set()?

Python 如何在Django REST Framework ModelSerializer的创建函数中使用field.set()?,python,django,django-rest-framework,Python,Django,Django Rest Framework,我有一个名为RoomMarket的中间模型,连接两个相关模型市场-房间市场-房间。当我试图使用可写嵌套序列化程序插入RoomMarket的记录时,我遇到了一个错误: /room_markets/ 禁止直接分配到多对多集合的前端。改为使用regions.set() 这是我简化的模型.py: class RecordStatus: published = 'Published' drafted = 'Drafted' hidden = 'Hidden' status

我有一个名为
RoomMarket
的中间模型,连接两个相关模型<代码>市场-
房间市场
-
房间
。当我试图使用可写嵌套序列化程序插入
RoomMarket
的记录时,我遇到了一个错误:

/room_markets/
禁止直接分配到多对多集合的前端。改为使用regions.set()

这是我简化的
模型.py

class RecordStatus:
    published = 'Published'
    drafted = 'Drafted'
    hidden = 'Hidden'
    status = [
        (published, 'Published'),
        (drafted, 'Drafted'),
        (hidden, 'Hidden'),
    ]


class Market(models.Model, RecordStatus):
    name = models.CharField(max_length=100)
    regions = models.ManyToManyField(Region)
    languages = models.ManyToManyField(Language)
    status = models.CharField(max_length=20, choices=RecordStatus.status, default=RecordStatus.published)

    @property
    def get_product_variations(self):
        return Product.objects.filter(distributor__region__market=self).distinct().count()


class Room(models.Model, RecordStatus):
    style = models.ForeignKey(Style, on_delete=models.CASCADE)
    markets = models.ManyToManyField(Market, through='RoomMarket')
    image = models.ImageField(upload_to='room_images', width_field=None, height_field=None,
                              max_length=250, null=True, blank=True)
    name = models.CharField(max_length=50)
    status = models.CharField(max_length=20, choices=RecordStatus.status, default=RecordStatus.published)


class RoomMarket(models.Model):
    market = models.ForeignKey(Market, on_delete=models.CASCADE)
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    landing_page = models.BooleanField(blank=True, null=True)

    def __str__(self):
        return '%s - %s' % (self.market, self.room)
class CustomRelatedField(serializers.RelatedField):
    def display_value(self, instance):
        return instance

    def to_representation(self, value):
        return str(value)

    def to_internal_value(self, data):
        model = self.queryset.model
        return model.objects.get(id=data)


class MarketSerializer(serializers.ModelSerializer):
    regions = CustomRelatedField(many=True, queryset=Region.objects.all())
    languages = CustomRelatedField(many=True, queryset=Language.objects.all())
    variation = serializers.ReadOnlyField(source='get_product_variations')
    landing_page = serializers.SerializerMethodField(source='get_landing_page')

    class Meta:
        model = Market
        fields = ['id', 'regions', 'languages', 'name', 'status', 'variation', 'landing_page']
        depth = 1

    @staticmethod
    def get_landing_page(market):
        queryset = RoomMarket.objects.filter(market=market)
        if queryset.exists():
            for r in queryset:
                return r.room.id
        else:
            return '-'


class RoomSerializer(serializers.ModelSerializer):
    style = CustomRelatedField(many=False, queryset=Style.objects.all())
    markets = CustomRelatedField(many=True, queryset=Market.objects.all())

    class Meta:
        model = Room
        fields = ['id', 'markets', 'style', 'image', 'name', 'status']


class RoomMarketSerializer(serializers.ModelSerializer):
    market = MarketSerializer()
    room = CustomRelatedField(many=False, queryset=Room.objects.all())

    class Meta:
        model = RoomMarket
        fields = ['id', 'market', 'room', 'landing_page']

    def create(self, validated_data):
        # create market data for Market model.
        market_data = validated_data.pop('market')
        market = Market.objects.create(**market_data)

        # create RoomMarket and set market FK.
        room_market = RoomMarket.objects.create(market=market, **validated_data)

        # return RoomMarket instance.
        return room_market
class RoomMarketView(viewsets.ModelViewSet):
    permission_classes = [permissions.DjangoModelPermissions]
    queryset = RoomMarket.objects.all()
    serializer_class = RoomMarketSerializer
这是我的
序列化程序.py

class RecordStatus:
    published = 'Published'
    drafted = 'Drafted'
    hidden = 'Hidden'
    status = [
        (published, 'Published'),
        (drafted, 'Drafted'),
        (hidden, 'Hidden'),
    ]


class Market(models.Model, RecordStatus):
    name = models.CharField(max_length=100)
    regions = models.ManyToManyField(Region)
    languages = models.ManyToManyField(Language)
    status = models.CharField(max_length=20, choices=RecordStatus.status, default=RecordStatus.published)

    @property
    def get_product_variations(self):
        return Product.objects.filter(distributor__region__market=self).distinct().count()


class Room(models.Model, RecordStatus):
    style = models.ForeignKey(Style, on_delete=models.CASCADE)
    markets = models.ManyToManyField(Market, through='RoomMarket')
    image = models.ImageField(upload_to='room_images', width_field=None, height_field=None,
                              max_length=250, null=True, blank=True)
    name = models.CharField(max_length=50)
    status = models.CharField(max_length=20, choices=RecordStatus.status, default=RecordStatus.published)


class RoomMarket(models.Model):
    market = models.ForeignKey(Market, on_delete=models.CASCADE)
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    landing_page = models.BooleanField(blank=True, null=True)

    def __str__(self):
        return '%s - %s' % (self.market, self.room)
class CustomRelatedField(serializers.RelatedField):
    def display_value(self, instance):
        return instance

    def to_representation(self, value):
        return str(value)

    def to_internal_value(self, data):
        model = self.queryset.model
        return model.objects.get(id=data)


class MarketSerializer(serializers.ModelSerializer):
    regions = CustomRelatedField(many=True, queryset=Region.objects.all())
    languages = CustomRelatedField(many=True, queryset=Language.objects.all())
    variation = serializers.ReadOnlyField(source='get_product_variations')
    landing_page = serializers.SerializerMethodField(source='get_landing_page')

    class Meta:
        model = Market
        fields = ['id', 'regions', 'languages', 'name', 'status', 'variation', 'landing_page']
        depth = 1

    @staticmethod
    def get_landing_page(market):
        queryset = RoomMarket.objects.filter(market=market)
        if queryset.exists():
            for r in queryset:
                return r.room.id
        else:
            return '-'


class RoomSerializer(serializers.ModelSerializer):
    style = CustomRelatedField(many=False, queryset=Style.objects.all())
    markets = CustomRelatedField(many=True, queryset=Market.objects.all())

    class Meta:
        model = Room
        fields = ['id', 'markets', 'style', 'image', 'name', 'status']


class RoomMarketSerializer(serializers.ModelSerializer):
    market = MarketSerializer()
    room = CustomRelatedField(many=False, queryset=Room.objects.all())

    class Meta:
        model = RoomMarket
        fields = ['id', 'market', 'room', 'landing_page']

    def create(self, validated_data):
        # create market data for Market model.
        market_data = validated_data.pop('market')
        market = Market.objects.create(**market_data)

        # create RoomMarket and set market FK.
        room_market = RoomMarket.objects.create(market=market, **validated_data)

        # return RoomMarket instance.
        return room_market
class RoomMarketView(viewsets.ModelViewSet):
    permission_classes = [permissions.DjangoModelPermissions]
    queryset = RoomMarket.objects.all()
    serializer_class = RoomMarketSerializer
这是我的
视图。py

class RecordStatus:
    published = 'Published'
    drafted = 'Drafted'
    hidden = 'Hidden'
    status = [
        (published, 'Published'),
        (drafted, 'Drafted'),
        (hidden, 'Hidden'),
    ]


class Market(models.Model, RecordStatus):
    name = models.CharField(max_length=100)
    regions = models.ManyToManyField(Region)
    languages = models.ManyToManyField(Language)
    status = models.CharField(max_length=20, choices=RecordStatus.status, default=RecordStatus.published)

    @property
    def get_product_variations(self):
        return Product.objects.filter(distributor__region__market=self).distinct().count()


class Room(models.Model, RecordStatus):
    style = models.ForeignKey(Style, on_delete=models.CASCADE)
    markets = models.ManyToManyField(Market, through='RoomMarket')
    image = models.ImageField(upload_to='room_images', width_field=None, height_field=None,
                              max_length=250, null=True, blank=True)
    name = models.CharField(max_length=50)
    status = models.CharField(max_length=20, choices=RecordStatus.status, default=RecordStatus.published)


class RoomMarket(models.Model):
    market = models.ForeignKey(Market, on_delete=models.CASCADE)
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    landing_page = models.BooleanField(blank=True, null=True)

    def __str__(self):
        return '%s - %s' % (self.market, self.room)
class CustomRelatedField(serializers.RelatedField):
    def display_value(self, instance):
        return instance

    def to_representation(self, value):
        return str(value)

    def to_internal_value(self, data):
        model = self.queryset.model
        return model.objects.get(id=data)


class MarketSerializer(serializers.ModelSerializer):
    regions = CustomRelatedField(many=True, queryset=Region.objects.all())
    languages = CustomRelatedField(many=True, queryset=Language.objects.all())
    variation = serializers.ReadOnlyField(source='get_product_variations')
    landing_page = serializers.SerializerMethodField(source='get_landing_page')

    class Meta:
        model = Market
        fields = ['id', 'regions', 'languages', 'name', 'status', 'variation', 'landing_page']
        depth = 1

    @staticmethod
    def get_landing_page(market):
        queryset = RoomMarket.objects.filter(market=market)
        if queryset.exists():
            for r in queryset:
                return r.room.id
        else:
            return '-'


class RoomSerializer(serializers.ModelSerializer):
    style = CustomRelatedField(many=False, queryset=Style.objects.all())
    markets = CustomRelatedField(many=True, queryset=Market.objects.all())

    class Meta:
        model = Room
        fields = ['id', 'markets', 'style', 'image', 'name', 'status']


class RoomMarketSerializer(serializers.ModelSerializer):
    market = MarketSerializer()
    room = CustomRelatedField(many=False, queryset=Room.objects.all())

    class Meta:
        model = RoomMarket
        fields = ['id', 'market', 'room', 'landing_page']

    def create(self, validated_data):
        # create market data for Market model.
        market_data = validated_data.pop('market')
        market = Market.objects.create(**market_data)

        # create RoomMarket and set market FK.
        room_market = RoomMarket.objects.create(market=market, **validated_data)

        # return RoomMarket instance.
        return room_market
class RoomMarketView(viewsets.ModelViewSet):
    permission_classes = [permissions.DjangoModelPermissions]
    queryset = RoomMarket.objects.all()
    serializer_class = RoomMarketSerializer
我用于发布数据的JSON格式:

{
    "market": {
        "regions": [1,2],
        "languages": [1,2],
        "name": "Asia",
        "status": "Published"
    },
    "room": 2,
    "landing_page": true
}

我已经读过一些关于这个问题的SO问题,但大多数情况下都是在
ModelSerializer
类中的Form/View而不是
create
函数上。我应该在中间模型
ModelSerializer
类的
create
函数中更改什么?

问题是,当您创建
market
实例时,您将
region
language
对象传递给
create()
方法。您应该将其传递给
set()

def create(self, validated_data):
    # create market data for Market model.
    market_data = validated_data.pop('market')
    regions = market_data.pop("regions")
    languages = market_data.pop("languages")
    market = Market.objects.create(**market_data)
    market.regions.set(regions)
    market.languages.set(languages)

谢谢@neverwanner向我解释。我可以将此应用于
更新
功能吗?因为我确信我还需要明确定义
update
函数。@Nathan欢迎!当然你可以在更新中使用它。但是请注意,
set()
替换相关对象集。如果您不需要它,可能最好在
update()
中使用
add()
。有关更多详细信息,请查看文档的相关部分: