Serializer用于自定义用户模型

时间:2017-05-16 14:31:30

标签: django django-models django-serializer

我是Django 1.9的新手,Rest Framework我有一个models.py如下:

class UniservedTeam(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE)
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    Role = ArrayField(models.CharField(max_length=1000), blank=True,null=True)
    ContactNumber = models.CharField(max_length=100)

我所尝试的是: -

from rest_framework import serializers
from django.contrib.auth.models import User
from models import UniservedTeam

class UniservedTeamSerializer(serializers.ModelSerializer):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    Role = ArrayField(models.CharField(max_length=1000), blank=True,null=True)
    ContactNumber = serializers.CharField(max_length=100)

    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'city')

我应该为IdRole字段使用哪种序列化程序的方法? 如何为post和get方法编写序列化器?

如果我从序列化程序中删除“id”和“Role”字段,如下所示: -

class UniservedTeamSerializer(serializers.ModelSerializer):
    # city = serializers.CharField(source=UniservedTeam.city)
    # id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    # Role = ArrayField(models.CharField(max_length=1000), blank=True,null=True)
    ContactNumber = serializers.CharField(source='UniservedTeam.ContactNumber')

    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'ContactNumber')

我的shell输出如下:

>>> from projectmanagement.serializers import UniservedTeamSerializer
>>> users = UniservedTeam.objects.all()
>>> serializer = UniservedTeamSerializer(users, many=True)
>>> serializer
UniservedTeamSerializer([<UniservedTeam: UniservedTeam object>], many=True):
    id = IntegerField(label='ID', read_only=True)
    username = CharField(help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=30, validators=[<django.core.validators.RegexValidator object>, <UniqueValidator(queryset=User.objects.all())>])
    password = CharField(max_length=128)
    first_name = CharField(allow_blank=True, max_length=30, required=False)
    last_name = CharField(allow_blank=True, max_length=30, required=False)
    email = EmailField(allow_blank=True, label='Email address', max_length=254, required=False)
    ContactNumber = CharField(source='UniservedTeam.ContactNumber')

错误: -

>>> serializer.data
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/piyush/.environments/awsd/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 674, in data
    ret = super(ListSerializer, self).data
  File "/home/piyush/.environments/awsd/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 239, in data
    self._data = self.to_representation(self.instance)
  File "/home/piyush/.environments/awsd/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 614, in to_representation
    self.child.to_representation(item) for item in iterable
  File "/home/piyush/.environments/awsd/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 463, in to_representation
    attribute = field.get_attribute(instance)
  File "/home/piyush/.environments/awsd/local/lib/python2.7/site-packages/rest_framework/fields.py", line 422, in get_attribute
    raise type(exc)(msg)
AttributeError: Got AttributeError when attempting to get a value for field `username` on serializer `UniservedTeamSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `UniservedTeam` instance.
Original exception text was: 'UniservedTeam' object has no attribute 'username'.

1 个答案:

答案 0 :(得分:2)

首先,在定义onetonone字段时,related_name约束比我们想象的更有帮助。 您需要在模型和序列化器中进行一些更改。

在models.py中,

class UniservedTeam(models.Model): 
    user = models.OneToOneField(User, related_name='userprofile', on_delete=models.CASCADE)

为用户定义related_name。

在序列化程序中,

class UserSerializer(serializers.ModelSerializer):  
    ContactNumber = serializers.CharField(source='userprofile.ContactNumber')
    class Meta: 
        model = User 
        fields = ('id', 'username', 'password', 'first_name', 'ContactNumber')

希望这有效

修改

related_name属性指定从用户模型返回到模型的反向关系的名称。

如果您没有指定related_name,Django会使用带有suffix_set的模型名称自动创建一个,例如User.map_set.all()。

如果您指定,例如在User模型上的related_name = maps,User.map_set仍然可以工作,但是User.maps。语法显然有点清洁,不那么笨重;例如,如果您有一个用户对象current_user,则可以使用current_user.maps.all()来获取与current_user有关系的Map模型的所有实例。

有关文档,请here

此外,如果您想在User模型中访问Userprofile的所有字段,您可以将序列化程序传递给用户序列化程序,如下所示,

class UniservedTeamSerializer(serializers.ModelSerializer):
    city = serializers.CharField(source=UniservedTeam.city)
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    Role = ArrayField(models.CharField(max_length=1000), blank=True,null=True)
    ContactNumber = serializers.CharField(source='UniservedTeam.ContactNumber')

在你的UserSerializer中,

class UserSerializer(serializers.ModelSerializer):  
    user_profile_details = UniservedTeamSerializer(source='userprofile', many=True)
    class Meta: 
        model = User 
        fields = ('id', 'username', 'password', 'first_name', 'user_profile_details')

序列化程序输出现在将在标记user_profile_details下包含UniservedTeamSerializer数据。

有关序列化程序的更多信息,documentation几乎涵盖了所有关于序列化程序的内容。

<强>更新

来自文档

  

序列化程序允许将复杂数据(如查询集和模型实例)转换为本机Python数据类型,然后可以轻松地将其呈现为JSON,XML或其他内容类型。序列化程序还提供反序列化,允许在首次验证传入数据后将解析后的数据转换回复杂类型。

     

REST框架中的序列化程序与Django的Form和ModelForm类非常相似。我们提供了一个Serializer类,它为您提供了一种强大的通用方法来控制响应的输出,以及一个ModelSerializer类,它提供了一个有用的快捷方式来创建处理模型实例和查询集的序列化器。

Serializers将对象转换为本机python数据类型,以完成序列化过程,需要将数据呈现为相应的格式(json,xml)。