我是Django领域的新手,但看到那里有很多“神奇”。我正在使用Django REST Framework并创建允许免费用户注册的应用程序。我的用户需要一些Django用户不具备的其他字段。所以我用Google搜索扩展用户。有一种想法应该通过创建类似的东西来完成
class MyUser(models.Model):
user = models.ForeignKey(User, unique=True)
city = models.CharField(max_length=50, blank=True, default='')
这很好,但我有这个序列化器
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = MyUser
fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'city')
所以,问题是这个序列化器在这里做了一些“魔术”。它试图找出应该建模的领域...... 我想让用户在这里列出字段,这些字段在用户中,“城市”是新的自定义字段。 Serializer没有得到应该在用户模型中查看。
我在这里缺少什么?如何告诉这个序列化器我想要用户内的一些字段?我也需要能够创建用户。
答案 0 :(得分:18)
显然,我没有足够的声誉在答案下发表评论。但是要详细说明凯文斯通所描述的内容,如果你的模型如下:
class AppUser(models.Model):
user = models.OneToOneField(User)
ban_status = models.BooleanField(default=False)
您可以执行以下操作来创建自定义用户和django用户:
class AppUserSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username')
email = serializers.CharField(source='user.email')
password = serializers.CharField(source='user.password')
ban_status = serializers.Field(source='ban_status')
class Meta:
model = AppUser
fields = ('id', 'username', 'email', 'password', 'ban_status')
def restore_object(self, attrs, instance=None):
"""
Given a dictionary of deserialized field values, either update
an existing model instance, or create a new model instance.
"""
if instance is not None:
instance.user.email = attrs.get('user.email', instance.user.email)
instance.ban_status = attrs.get('ban_status', instance.ban_status)
instance.user.password = attrs.get('user.password', instance.user.password)
return instance
user = User.objects.create_user(username=attrs.get('user.username'), email= attrs.get('user.email'), password=attrs.get('user.password'))
return AppUser(user=user)
答案 1 :(得分:13)
好的,有几件事。您想为您的用户模型扩展程序创建OneToOneField
。
class MyUser(models.Model):
user = models.OneToOneField(User)
city = models.CharField(max_length=50, blank=True, default='')
现在,Django Rest Framework的强大功能是,您可以构建序列化程序,在序列化时从这两个模型中获取数据。
class UserSerializer(serializers.ModelSerializer):
city = serializers.CharField(source='myuser.city')
class Meta:
model = User
fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'city')
最后,在您创建用户的位置,由于您使用的是自定义字段,因此您需要实现自己的restore_object()
,从输入数据构建两个模型。
此外,在Django中创建用户有点不同,您需要调用create_user()
并提供经过哈希处理的密码,因此它不像在串行器中存储字段那么简单。
答案 2 :(得分:1)
如果您使用的是django 1.5或更高版本,那么请使用custom user model,这样用户模型将拥有自己的专用表格,然后序列化程序将正确选取字段。
答案 3 :(得分:1)
使用Django Rest Framework时,必须小心。任何自定义用户模型都无法使用内置令牌身份验证。在你能做到这一点之前,我建议你在自定义模型中使用OneToOneField和用户。您的自定义模型将包含您要保留的额外字段。一对一允许您从自定义用户和用户的自定义用户访问用户。
答案 4 :(得分:1)
如果在文档中更容易找到这个用例,那就太好了。正如@jamod指出的那样,在DRF 3中,你可以找到它here:
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()
class Meta:
model = User
fields = ('username', 'email', 'profile')
def create(self, validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create(**validated_data)
Profile.objects.create(user=user, **profile_data)
return user
答案 5 :(得分:1)
我更喜欢使用django signals模块,它会在发生某些事情时向应用程序发送信号,除此之外还可以让你在其他功能之前/之后调用自己的功能。我的回答类似于Stuart的答案,但是将所有代码与您的新扩展类保持在一个地方(如果您想稍后删除该配置文件或更改其名称,您不必在其他任何地方查找)。
以下代码列出了您的扩展类模型(在本例中为用户配置文件),然后在创建用户模型时创建一个空实例,然后通过保存父项来保存具有新信息的实例(必须自行添加)用户实例ie - user.save()
<强> models.py 强>
from django.db.models.signals import post_save
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model): #This extends the user class to add profile information
user = models.OneToOneField(User, on_delete=models.CASCADE)
#add your extra traits here: is_nice, is_shwifty, address, etc.
is_nice = models.BooleanField(default=True, blank=True)
# a user model was just created! This now creates your extended user (a profile):
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
# instance is the user model being saved.
Profile.objects.create(user=instance)
# a user model was just saved! This now saves your extended user (a profile):
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
如果您没有ProfileSerializer: serializers.py
#use hyperlinkedmodelserializer for easy api browsing + clicking
class ProfileSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer()
class Meta:
model = Profile
fields = ('url', 'user', 'is_nice')
创建用户并保存用户后,您将有一个空的user.profile来添加信息。例如,在运行python manage.py shell
之后
尝试:
from backend.models import User, Profile
#create your user
user=User(username="GravyBoat")
user.save()
#now update your user's profile
user.profile.is_nice=False
#that's one mean gravy boat
user.save()
user.profile.is_nice
#False