在视图上生成Django HiddenField值

时间:2018-03-29 13:45:32

标签: django django-rest-framework django-views

概述需要为隐藏字段生成代号,以便将其发送到外部API(1),之后包括数据库(2)中生成的代号字段。

问题:如何将生成的代号(HiddenField)发送到数据库?

models.py

class Category(Model):
    name = models.CharField(max_length=45)

class Animal(Model):
    name = models.CharField(max_length=45)
    codename = models.CharField(max_length=45)
    categories = models.ManyToManyField(Category)

serializers.py

class CategorySerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Category
        fields = '__all__'

class AnimalSerializer(serializers.ModelSerializer):

    codename = serializers.HiddenField(default="auto_replace_me")

    class Meta:
        model = models.Animal
        fields = '__all__'

views.py

class CategoryViewSet(ModelViewSet):
    queryset = models.Category.objects.all()
    serializer_class = serializers.CategorySerializer


class AnimalViewSet(ModelViewSet, CreateModelMixin):

    queryset = models.Animal.objects.all()
    serializer_class = serializers.AnimalSerializer

    def create(self, request, *args, **kwargs):

        codename = generate_codename()

        # (1) external API request (with codename included on request) and returns a boolean `result`

        if result:

            # will call create method from parent class BUT
            # (2) it needs to save the codename in database

            return super(AnimalViewSet, self).create(request, *args, **kwargs)
        else:
            return HttpResponseServerError()


def generate_codename():
    return ''.join([random.choice(string.ascii_letters) for n in range(10)])

3 个答案:

答案 0 :(得分:0)

以下代码应该完成这项工作:

class AnimalViewSet(ModelViewSet, CreateModelMixin):

    queryset = models.Animal.objects.all()
    serializer_class = serializers.AnimalSerializer

    def perform_create(serializer, codename):
        serializer.save(codename=codename)

    def create_with_codename(self, request, codename, *args, **kwargs):
        # this is almost the same as CreateModelMixin 'create' 
        # but with one change: passing codename to 'perform_create' method

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        instance = self.perform_create(serializer, codename)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def create(self, request, *args, **kwargs):

        codename = generate_codename()

        # (1) external API request (with codename included on request) and returns a boolean `result`

        if result:

            # will call create method from parent class BUT
            # (2) it needs to save the codename in database

            return self.create_with_codename(request, codename, *args, **kwargs)
        else:
            return HttpResponseServerError()

基本上,您应该编写自己的函数create_with_codename来更改CreateModelMixin def create(self, request, *args, **kwargs)的默认行为 最重要的是将codename参数传递给perform_create。根据{{​​3}},每当您需要保存序列化程序并附加其他值时,您应该使用serializer.save(extra_field=extra_value)

答案 1 :(得分:0)

如下所示更改views.py

from rest_framework.response import Response


class AnimalViewSet(ModelViewSet):
    queryset = models.Animal.objects.all()
    serializer_class = serializers.AnimalSerializer

    def create(self, request, *args, **kwargs):
        codename = generate_codename()

        # (1) external API request (with codename included on request) and returns a boolean `result`

        if result:

            # will call create method from parent class BUT
            # (2) it needs to save the codename in database
            request.data._mutable = True
            request.data['codename'] = codename
            animalserializer = AnimalSerializer(request.data)

            return Response(data=animalserializer.data)
        else:
            return HttpResponseServerError()

答案 2 :(得分:0)

在向你们学习之后,我得到了这个解决方案(只更改了views.py ):

<强> views.py

class CategoryViewSet(ModelViewSet):
    queryset = models.Category.objects.all()
    serializer_class = serializers.CategorySerializer


class AnimalViewSet(ModelViewSet, CreateModelMixin):

    queryset = models.Animal.objects.all()
    serializer_class = serializers.AnimalSerializer

    codename = None

    def perform_create(self, serializer):
        serializer.save(codename=self.codename)

    def create(self, request, *args, **kwargs):

        self.codename = generate_codename()

        # (1) external API request (with codename included on request) and returns a boolean `result`

        if result:

            # will call create method from parent class BUT
            # (2) it needs to save the codename in database

            return super(AnimalViewSet, self).create(request, *args, **kwargs)
        else:
            return HttpResponseServerError()


def generate_codename():
    return ''.join([random.choice(string.ascii_letters) for n in range(10)])