如何在 Django 休息框架上 request.method==PUT,POST

How to request.method==PUT, POST on Django rest framework

我正在使用 Django REST Framework 序列化一些模型。

这是我的 Match 序列化器模型

class MatchSerializer(serializers.ModelSerializer):

    field = serializers.SlugRelatedField(queryset=Field.objects.all(),slug_field='name')

    class Meta:
        model = Match
        fields = ('url', 'id', 'home_team', 'away_team', 'field', 'match_date', 'check_match_away_team', 'status_challenge', 'home_team_players_accept', 'away_team_players_accept', 'home_team_players_cancel', 'away_team_players_cancel', 'fichaje_players_match',)

Match模型中,字段如下:

我的情况是,当我通过 curl 和我的移动 iOS 应用程序客户端更新一个 Match 对象时,我遇到以下情况:

我有这样一条记录:

{
    "url": "https://myserver/api/matchs/29/",
    "id": 29,
    "home_team": "Manchester United",
    "away_team": "Sempiternos FC",
    "field": "Joga Bonito",
    "match_date": "2017-01-02T09:00:05Z",
    "check_match_away_team": true,
    "status_challenge": "Aceptado",
    "home_team_players_accept": [
        "paoc",
        "nuevo"
    ],
    "away_team_players_accept": [
        "mike",
        "giraldoesteban"
    ],
    "home_team_players_cancel": [
        "erick"
    ],
    "away_team_players_cancel": [
        "Bluse"
    ],
    "fichaje_players_match": [
        "Oliver"
    ]
}

当我通过 curl 工具命令对该记录进行 PUT 操作时,仅在 status_challenge 字段中执行我的更新,将其值从 Aceptado 更改为 Pendiente更新 PUT 已完成,我的 home_team_players_acceptaway_team_players_accepthome_team_players_cancelaway_team_players_cancelfichaje_players_match 数组字段设置为空白或空,它们的值被删除:

bgarcial@elpug : ~
[0] % curl -X PUT https://myserver/api/matchs/29/ -d "home_team=Manchester United&away_team=Sempiternos FC&field=Joga Bonito&match_date=2017-01-2T09:00:05Z&check_match_away_team=true&status_challenge=Pendiente" 
{"url":"https://myserver/api/matchs/29/","id":29,"home_team":"Manchester United","away_team":"Sempiternos FC","field":"Joga Bonito","match_date":"2017-01-02T09:00:05Z","check_match_away_team":true,"status_challenge":"Pendiente","home_team_players_accept":[],"away_team_players_accept":[],"home_team_players_cancel":[],"away_team_players_cancel":[],"fichaje_players_match":[]}%           
bgarcial@elpug : ~
[0] % 

目前我的比赛记录是这样的:

当我通过消耗 API

的移动应用程序执行更新时,也会发生这种情况

我尝试在我的视图集中处理 request.method == 'PUT' 这种情况:

class MatchViewSet(viewsets.ModelViewSet):

    queryset = Match.objects.all()
    serializer_class = MatchSerializer
    filter_fields = ('home_team','away_team', 'status_challenge', 'fichaje_players_match', )

    @api_view(['PUT'])
    def match_detail(request, pk):
        if request.method == 'PUT':
            serializer = MatchSerializer()
            if serializer.is_valid():
                serializer.save()
                return Response(serializer)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

结果是一样的,我暂时不知道如何解决这种情况,the guide我还不够清楚

如何更新模型序列化程序 Matchstatus_challenge 字段,而不是让上面引用的玩家字段保持空白或删除其内容?


更新

传递性的方式如下:

有我的定制User型号

class User(AbstractBaseUser, PermissionsMixin):
    ... other attributes ...   

    team = models.ForeignKey(
        'games_information.Team',
        null=True,
        blank=True,
        verbose_name='Equipo en el que juega',    
    )

User 序列化程序:

class UserSerializer(serializers.ModelSerializer):
    username = serializers.CharField(validators=[UniqueValidator(queryset=User.objects.all(), message='Lo sentimos, existe un fichaje con este nombre de usuario')])
    email = serializers.EmailField(validators=[UniqueValidator(queryset=User.objects.all(), message='Lo sentimos, alguien ya ha sido fichado con este correo electrónico')])

    def create(self, validated_data):
        password = validated_data.pop('password', None)
        instance = self.Meta.model(**validated_data)
        if password is not None:
            instance.set_password(password)
        instance.save()
        return instance

    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            if attr == 'password':
                instance.set_password(value)
            else:
                setattr(instance, attr, value)
        instance.save()
        return instance

    class Meta:
        model = User
        fields = ('url', 'username', 'password', 'first_name','last_name',
                  'age', 'sex', 'photo', 'email', 'is_player', 'team',
                  'position', 'is_staff', 'is_active', 'is_superuser',
                  'is_player', 'weight', 'height', 'nickname',
                  'number_matches', 'accomplished_matches',
                  'time_available', 'leg_profile', 'number_shirt_preferred',
                  'team_support', 'player_preferred', 'last_login',)

Team 模型有一个 ManyToMany 字段到 User 模型:

class Team(models.Model):

    ... other fields ...

    players = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='players',
        blank=True,
    )

这是我的TeamSerializer

class TeamSerializer(serializers.ModelSerializer):

    name = serializers.CharField(validators=[UniqueValidator(queryset=Team.objects.all(), message='Lo sentimos, ya existe un equipo con este nombre')])
    place_origin = serializers.SlugRelatedField(queryset=Field.objects.all(),slug_field='name')

    class Meta:
        model = Team
        fields = ('url', 'name', 'image', 'players', 'modality', 'branch', 'category', 'category_name', 'place_origin', 'game_day',)

匹配模型,有home_team_players_acceptaway_team_players_accepthome_team_players_cancelaway_team_players_cancelfichaje_players_match字段,都在ManyToMany关系中使用 User 模型 (settings.AUTH_USER_MODEL)

class Match(models.Model):

       ... other fields ...
       STATUS_CHALLENGE_CHOICES = (
           (ACCEPTED_CHALLENGE, u'Aceptado'),
           (PENDING_CHALLENGE, u'Pendiente'),
           (CANCELLED_CHALLENGE, u'Cancelado'),
           (FICHAJE, u'Fichaje'),
       ) 
       status_challenge = models.CharField(
           choices=STATUS_CHALLENGE_CHOICES,
           max_length=40,
           default=True,
           blank=False,
           verbose_name='Estado del desafío'
        )
        home_team_players_accept = models.ManyToManyField(
            settings.AUTH_USER_MODEL,
            related_name='home_team_players_accept',
            blank=True,)

        away_team_players_accept = models.ManyToManyField(
            settings.AUTH_USER_MODEL,
            related_name='away_team_players_accept',
            blank=True,)

        home_team_players_cancel = models.ManyToManyField(
            settings.AUTH_USER_MODEL,
            related_name='home_team_players_cancel',
            blank=True,)

        away_team_players_cancel = models.ManyToManyField(
            settings.AUTH_USER_MODEL,
            related_name='away_team_players_cancel',
            blank=True,)

        fichaje_players_match = models.ManyToManyField(
            settings.AUTH_USER_MODEL,
            related_name='fichaje_players_match',
            blank=True,)

这是我的 Match 序列化程序:

class MatchSerializer(serializers.ModelSerializer):

        field = serializers.SlugRelatedField(queryset=Field.objects.all(),slug_field='name')

        class Meta:
            model = Match
            fields = ('url', 'id', 'home_team', 'away_team', 'field', 'match_date', 'check_match_away_team', 'status_challenge', 'home_team_players_accept', 'away_team_players_accept', 'home_team_players_cancel', 'away_team_players_cancel', 'fichaje_players_match',)

不方便的是我在上面最初描述的。当我申请更新到匹配端点记录时,在status_challenge字段中home_team_players_acceptaway_team_players_accepthome_team_players_cancelaway_team_players_cancel和[=37=中的记录] 字段被删除或设置为空白

您需要部分更新。 PUT 调用 update() 和 PATCH 调用 partial_update()。 唯一的区别是 partial=True (PATCH) 或 partial=False (PUT)。您可以在视图中初始化序列化程序时自行设置部分。

您可以像在 Django REST 框架代码 (mixins.py) 中那样使用 PUT 执行部分更新:

def update(self, request, *args, **kwargs):
    kwargs['partial'] = True
    return super(YourCustomView, self).update(request, *args, **kwargs)