У меня есть промежуточная модель под названием RoomMarket
, соединяющая 2 связанные модели. Market
- RoomMarket
- Room
. Когда я попытался вставить запись для RoomMarket
, используя вложенный сериализатор, доступный для записи, я получил ошибку:
TypeError at / room_markets /
Прямое назначение на переднюю сторону многие-ко-многим набор запрещен. Вместо этого используйте region.set ().
Вот мой упрощенный models.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)
Вот мой serializers.py
:
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
Вот мой views.py
:
class RoomMarketView(viewsets.ModelViewSet):
permission_classes = [permissions.DjangoModelPermissions]
queryset = RoomMarket.objects.all()
serializer_class = RoomMarketSerializer
Формат JSON, который я использую для POST-данных:
{
"market": {
"regions": [1,2],
"languages": [1,2],
"name": "Asia",
"status": "Published"
},
"room": 2,
"landing_page": true
}
Я прочитал несколько SO вопросов по этому вопросу, но большинство случаев касаются формы / представления, а не функции create
в ModelSerializer
класс. Что я должен изменить в create
функции моей промежуточной модели ModelSerializer
класса?