首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Django Rest Framework将对象附加到多个字段中,而不删除前一个字段

Django Rest Framework将对象附加到多个字段中,而不删除前一个字段
EN

Stack Overflow用户
提问于 2021-04-03 12:07:11
回答 2查看 1.1K关注 0票数 1

我是DRF的新手,不知道如何在不删除前一个字段的情况下将一个对象附加到多个字段中。

我使用修补程序更新字段监视器,但是前面的值被实际值所替代。我想把它加上去。

API GET是:

代码语言:javascript
运行
复制
{
    "id": 1,
    "created": "2018-05-02T23:43:07.605000Z",
    "modified": "2021-04-03T10:25:12.280896Z",
    "companies_house_id": "",
    "name": "Ellison PLC",
    "description": "",
    "date_founded": "2018-04-28",
    "country": 4,
    "creator": 7,
    "monitors": [
        3
    ]
}

PATCH {"monitors":[11]}之后,我得到:

代码语言:javascript
运行
复制
{
    "id": 1,
    "created": "2018-05-02T23:43:07.605000Z",
    "modified": "2021-04-03T10:25:12.280896Z",
    "companies_house_id": "",
    "name": "Ellison PLC",
    "description": "",
    "date_founded": "2018-04-28",
    "country": 4,
    "creator": 7,
    "monitors": [
        11
    ]
}

我希望最终的GET API是"monitors": [3, 11]

models.py

代码语言:javascript
运行
复制
class Company(TimeStampedModel):
    companies_house_id = models.CharField(max_length=8, blank=True)
    name = models.CharField(max_length=200, blank=True)
    description = models.TextField(blank=True)
    date_founded = models.DateField(null=True, blank=True)
    country = models.ForeignKey(Country, on_delete=models.PROTECT, blank=True)
    creator = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        related_name='companies_created'
    )
    monitors = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        blank=True,
        related_name='companies_monitored',
        help_text='Users who want to be notified of updates to this company'
    )

    def __unicode__(self):
        return u'{0}'.format(self.name)

serializers.py

代码语言:javascript
运行
复制
from rest_framework import serializers
from .models import Company
from django.contrib.auth import get_user_model

class CompanySerializer(serializers.ModelSerializer):

    class Meta:
        model = Company
        fields = '__all__'

class UserSerializer(serializers.ModelSerializer):
    companies_monitored = CompanySerializer(many=True, read_only=True)
    # companies_moniotred = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

    class Meta:
        model = get_user_model()
        fields = ('id', 'username', 'companies_monitored')

views.py

代码语言:javascript
运行
复制
class CompanyDetailsView(generics.RetrieveUpdateAPIView):
    queryset = Company.objects.all()
    serializer_class = CompanySerializer


class UserList(generics.ListCreateAPIView):
    queryset = get_user_model().objects.all()
    serializer_class = UserSerializer


class UserDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = get_user_model().objects.all()
    serializer_class = UserSerializer


    def get_object(self, username):
        username = get_object_or_404(get_user_model(), username=username)
        return username

    def get(self, request, username):
        username = self.get_object(username)
        serializer = UserSerializer(username)
        return Response(serializer.data)

urls.py

代码语言:javascript
运行
复制
from django.conf.urls import url
from django.urls import path

from . import views
from .views import CompanyDetailsView, UserList, UserDetail
urlpatterns = [
    path('details/<int:pk>/', CompanyDetailsView.as_view(), name='company_details'),
    path('users/<str:username>/', UserDetail.as_view(), name='profile_view'),
]
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-04-04 09:33:42

PATCH方法使用不同的序列化程序。

代码语言:javascript
运行
复制
class CompanyDetailsView(generics.RetrieveUpdateAPIView):
    queryset = Company.objects.all()
    serializer_class = CompanySerializer
    
    def get_serializer_class(self):
        if self.request.method == 'PATCH':
            return CompanyPatchSerializer
        return self.serializer_class

并处理序列化程序中所需的内容。

代码语言:javascript
运行
复制
class CompanyPatchSerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = '__all__'

    @transaction.atomic
    def update(self, instance, validated_data):
        if 'monitors' in validated_data:
            monitor_ids = validated_data.pop('monitors')
            # todo: handle get_or_create
        return super().update(instance, validated_data)

我不喜欢隐式m2m模型,所以我的建议也是添加through模型。

票数 0
EN

Stack Overflow用户

发布于 2021-04-04 09:37:02

我不建议重写修补程序方法,但是下面的代码应该可以完成此工作。

代码语言:javascript
运行
复制
def patch(self, request, *args, **kwargs):
    request.data._mutable = True
    new_monitors =  request.data.get('monitors')
    existing_monitors = Company.objects.get(kwargs.get('id')).values_list('monitors__id', flat=True)
    all_monitors = existing_monitors + new_monitors
    request.data.update({'monitors': set(all_monitors)})
    return self.partial_update(request, *args, **kwargs)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66930970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档