首页 > 解决方案 > Django 反向关系序列化器

问题描述

我正在尝试创建一个用于自学的项目,而现在,我被困在了这一点上。

它是一个活动策划者,每个活动都会有肉。活动的组织者可以为他的活动选择或创建新的肉类类型。活动创建后,客人可以从组织者挑选的选择池中选择他们喜欢的肉类。

例如,作为一个组织者,我可以说我会从一张MeatType有“鸡肉”、“火鸡”和“猪肉”的桌子上吃“鸡肉”、“火鸡”和“牛肉”。(组织者将创建一个新的MeatType并为他的活动选择它)

所以我有 3 个与这个特定问题相关的 Django 模型。

事件模型

class Event(models.Model):
   name = models.CharField(_('Event name'), max_length=255)
   capacity = models.IntegerField(_('Capacity'), null=True)
   address = models.CharField(_('Address'), max_length=255)
   date = models.DateTimeField(_('Event Date'), db_index=True)

   organizer = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('Organizer'), related_name='events',
                              on_delete=models.CASCADE)

肉类型号

class MeatType(models.Model):
   """
   A model just to hold meat type names on the database.
   This model will only have a "name" field which represents the Meat Type.
   For example, "Chicken" or "Beef"
   """
   name = models.CharField(_('Name'), max_length=255)

可用的肉类型号

class AvailableMeatType(models.Model):
    """
    Available meat types for the event selected by Organizer
    """
    event = models.ForeignKey(Event, verbose_name=_('Event'), related_name='available_meat_types',
                          on_delete=models.CASCADE)
    meat_type = models.ForeignKey(MeatType, verbose_name=_('Meat Type'), on_delete=models.CASCADE)

根据这个结构,要创建一个事件,组织者应该发送一个如下所示的请求:

    {
       "name": "Team BBQ",
       "capacity": 10,
       "address": "Down Town",
       "date": "2019-02-01T18:00",
       "available_meat_type_ids": [
           1, 
           2, 
           3
       ]    
    }

其中 1 , 2 和 3 是Meat TypeID,但会创建Available Meat Type如下对象: { 123, 1 } , { 123, 2} , { 123, 3} 其中 123 是创建的事件 ID

** 我的序列化器 **

class EventSerializer(serializers.ModelSerializer):
    """
    A serializer class for creating and listing events
    """
    organizer = serializers.PrimaryKeyRelatedField(read_only=True)
    available_meat_type_ids = serializers.PrimaryKeyRelatedField(
    many=True,
    read_only=True
)

    class Meta:
        model = Event
        fields = (
            'id',
            'name',
            'capacity',
            'address',
            'date',
            'organizer',
            'available_meat_type_ids'
        )
        read_only_fields = ('organizer', )

    def post(self, request, *args, **kwargs):
        """
        Create available meat type object
        """
        # I dont know what to do here
        pass

    @staticmethod
    def validate_date(date):
        # Date of the event can not be on the past
        if date < timezone.now():
            raise Exception("Date of the new event can not be on the past.")
        return date


class CreateAvailableMeatTypeSerializer(serializers.ModelSerializer):
    """
    A serializer for available meat type request.
    """
    event = serializers.PrimaryKeyRelatedField(required=True, queryset=Event.objects)
    meat_type = serializers.PrimaryKeyRelatedField(required=True, queryset=MeatType.objects)

    class Meta:
        model = AvailableMeatType
        fields = (
            'id',
        )

我不知道如何使它工作。我试图在网上搜索,但找不到任何有用的东西。

如何根据在事件创建请求中收到的肉类类型 ID 创建可用的肉类类型对象?

标签: djangodjango-modelsdjango-rest-frameworkserializationdjango-serializer

解决方案


我认为您可以通过以下方式简单地做到这一点:

class EventSerializer(serializers.ModelSerializer):

    organizer = serializers.PrimaryKeyRelatedField(read_only=True)
    available_meat_type_ids = serializers.PrimaryKeyRelatedField(
        many=True,
        read_only=True
    )
    meat_id = serailizers.IntegerField()

    class Meta:
        model = Event
        fields = (
            'id',
            'name',
            'capacity',
            'address',
            'date',
            'organizer',
            'available_meat_types',
            'meat_id'
        )
        read_only_fields = ('organizer', )
        write_only_fields = ('meat_id',)

    def create(self, validate_data):
      meat_id = validate_data.pop('meat_id')
      event = Event.objects.create(**validate_data)
      AvailableMeatType.objects.create(event=event, meat_type_id=meat_id)
      return event

有关更多详细信息,请查看 PrimaryKeyRelatedField 上的文档


推荐阅读