Django反向关系序列化器

时间:2019-01-02 21:54:28

标签: django django-models django-rest-framework serializer django-serializer

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

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

例如,作为组织者,我可以说我将在MeatType表中包含“ Chicken”,“ Turkey”和“ Pork”的“ Chicken”,“ Turkey”和“ Beef”。 (组织者将创建一个新的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 Type id,但将创建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创建可用的肉类对象?

1 个答案:

答案 0 :(得分:0)

我想您可以这样做:

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上的documentation