概述需要为隐藏字段生成代号,以便将其发送到外部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)])
答案 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)])