【问题标题】:Serializer for custom User model自定义用户模型的序列化器
【发布时间】:2017-05-16 14:31:30
【问题描述】:

我是 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”和“角色”字段,如下所示:-

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'.

【问题讨论】:

    标签: django django-models django-serializer


    【解决方案1】:

    首先,在定义 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 会自动使用您的模型名称和后缀集创建一个,例如 User.map_set.all()。

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

    对于文档,here

    另外,如果您想访问 User 模型中的所有 Userprofile 字段,您可以像这样将序列化程序传递给 User 序列化程序,

    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)。

    【讨论】:

    • 你能解释一下这个related_name='userprofile' 是干什么用的吗?我可以使用 userprofile 的任何内容吗?
    • 如何提及Role和'Id'等其他字段?
    • 我不能在单个序列化程序中这样做吗?
    • 是的,你可以这样做。但是只能检索或创建单个实例,通过使用嵌套序列化程序,可以检索或创建多个实例。
    • 希望你得到你想要的。
    猜你喜欢
    • 2016-08-08
    • 2013-05-10
    • 2015-12-14
    • 2014-10-05
    • 2017-04-08
    • 2018-02-04
    • 1970-01-01
    • 2015-07-07
    • 2016-11-21
    相关资源
    最近更新 更多