【问题标题】:Django Reverse Relation SerializerDjango 反向关系序列化器
【发布时间】:2019-01-02 21:54:27
【问题描述】:

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

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

例如,作为组织者,我可以说我将在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 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 创建可用的肉类类型对象?

【问题讨论】:

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


    【解决方案1】:

    我认为你可以这样做:

    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

    【讨论】:

    • 非常感谢您的回答,但后来我收到“TypeError at /api/events/ 'AvailableMeatType' instance expected, got ” @ruddra
    • 问题是,我需要提供肉类类型 ID 并创建可用肉类类型对象
    • 我假设您想在序列化器字段定义上编写 available_meat_types。但是create中的验证数据中没有肉id
    • 我在序列化程序中添加了一个新字段。但我忘了把它添加到fields 列表中。请查看更新后的答案
    猜你喜欢
    • 2020-03-24
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 2020-12-29
    • 2016-05-19
    • 2018-08-31
    • 1970-01-01
    • 2017-02-09
    相关资源
    最近更新 更多