我有两个模型,一个具有M2M关系和一个相关名称。我想在序列化程序和相关字段中包含所有字段。
models.py:
class Pizza(models.Model):
name = models.CharField(max_length=50, unique=True)
toppings = models.ManyToManyField(Topping, null=True, blank=True, related_name='pizzas')
class Topping(models.Model):
name = models.CharField(max_length=50, unique=True)
price = models.IntegerField(default=0)
serializer.py:
class ToppingSerializer(serializers.ModelSerializer):
class Meta:
model = Topping
fields = '__all__'
这样可行,但它不包含相关字段。
fields = ['name', 'price', 'pizzas']
这完全符合我的要求,但当Toppings模型有很多字段时会发生什么。我想做点什么:
fields = ['__all__', 'pizzas']
此语法导致错误说明:
字段名称
无效__all__
对模型
有没有办法实现想要的行为?或者在使用相关名称时必须手动输入字段?
答案 0 :(得分:23)
就像@DanEEStart所说,DjangoRestFramework没有一种简单的方法可以扩展所有' 所有'字段的值,因为get_field_names
方法似乎设计为to work that way。
但幸运的是,您可以覆盖此方法,以允许一种简单的方法来包含所有字段和关系,而无需枚举大量字段。
我像这样重写这个方法:
class ToppingSerializer(serializers.ModelSerializer):
class Meta:
model = Topping
fields = '__all__'
extra_fields = ['pizzas']
def get_field_names(self, declared_fields, info):
expanded_fields = super(ToppingSerializer, self).get_field_names(declared_fields, info)
if getattr(self.Meta, 'extra_fields', None):
return expanded_fields + self.Meta.extra_fields
else:
return expanded_fields
请注意,此方法仅更改此序列化程序的行为,extra_fields
属性仅适用于此序列化程序类。
如果您有大量这样的序列化程序,您可以创建一个中间类,将此get_fields_names
方法包含在一个位置,并多次重复使用。有人喜欢这样:
class CustomSerializer(serializers.HyperlinkedModelSerializer):
def get_field_names(self, declared_fields, info):
expanded_fields = super(CustomSerializer, self).get_field_names(declared_fields, info)
if getattr(self.Meta, 'extra_fields', None):
return expanded_fields + self.Meta.extra_fields
else:
return expanded_fields
class ToppingSerializer(CustomSerializer):
class Meta:
model = Topping
fields = '__all__'
extra_fields = ['pizzas']
class AnotherSerializer(CustomSerializer):
class Meta:
model = Post
fields = '__all__'
extra_fields = ['comments']
答案 1 :(得分:16)
我刚检查了Django Rest Framework的源代码。 框架中似乎不支持您想要的行为。
fields
选项必须是列表,元组或文本__all__
。
以下是相关源代码的片段:
ALL_FIELDS = '__all__'
if fields and fields != ALL_FIELDS and not isinstance(fields, (list, tuple)):
raise TypeError(
'The `fields` option must be a list or tuple or "__all__". '
'Got %s.' % type(fields).__name__
)
您无法在字段或列表中添加“所有”...
答案 2 :(得分:11)
一个老问题,但认为这可能在将来帮助其他人。
我刚刚遇到了类似的问题并得到了" 所有"通过按以下示例手动指定其他字段来工作选项。我不确定这是否也可以解决您的问题。它比我见过的任何东西都更清洁。
http://www.django-rest-framework.org/api-guide/relations/#nested-relationships
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = '__all__'
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True, read_only=True)
class Meta:
model = Album
fields = '__all__'
我认为这适用于同一页面上列出的任何其他相关字段选项:http://www.django-rest-framework.org/api-guide/relations/#serializer-relations
我正在使用Django Rest Framework版本3.6.2
请求的反向关系示例:
class TrackSerializer(serializers.ModelSerializer):
album = AlbumSerializer(source='album_id')
class Meta:
model = Track
fields = '__all__'
答案 3 :(得分:2)
您好我可以使用Django's _meta API来实现预期的结果,这似乎是自Django 1.11以来可用的。所以在我的序列化器中我做了:
model = MyModel
fields = [field.name for field in model._meta.fields]
fields.append('any_other_field')
在编程中,总有很多方法可以达到相同的效果,但上面的这个方法对我来说真的很有用。
干杯!
答案 4 :(得分:1)
包含序列化程序中定义的所有字段和其他字段,您只需说exclude = ()
class ToppingSerializer(serializers.HyperlinkedModelSerializer):
pizzas = '<>' #the extra attribute value
class Meta:
model = Topping
exclude = ()
这将使用额外参数pizzas列出所有字段值
答案 5 :(得分:0)
这就是我做到的方式,更容易
class OperativeForm(forms.ModelForm):
class Meta:
model = Operative
fields = '__all__'
exclude = ('name','objective',)
widgets = {'__all__':'required'}
答案 6 :(得分:0)
如果您基本上只是想在序列化对象中添加额外的信息,则根本不需要更改字段部分。要添加字段,请执行以下操作:
class MySerializer(serializers.ModelSerializer):
...
new_field = serializers.SerializerMethodField('new_field_method')
def new_field_method(self, modelPointer_):
return "MY VALUE"
那么您仍然可以使用
class Meta:
fields = '__all__'