[英]Django Rest Framework create user and user profile
I am trying to create the view that will create new user using my API.我正在尝试创建将使用我的 API 创建新用户的视图。 I am using a custom model for my User and also created a model called Profile to manage data that are not authentication related.
我正在为我的用户使用自定义模型,还创建了一个名为 Profile 的模型来管理与身份验证无关的数据。
I am new to the Django world and it can be quite difficult.我是 Django 世界的新手,这可能非常困难。
Here is my models.py这是我的models.py
class UserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('User must have an email address')
user = self.model(
email = self.normalize_email(email),
)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password):
user = self.create_user(email, password=password)
user.is_admin = True
user.save()
return user
class User(AbstractBaseUser):
objects = UserManager()
email = models.EmailField(unique=True, db_index=True)
created = models.DateTimeField('created', auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
is_active = models.BooleanField('active', default=True)
is_admin = models.BooleanField('admin', default=False)
USERNAME_FIELD = 'email'
ordering = ('created',)
def is_staff(self):
return self.is_admin
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
def get_short_name(self):
return self.email
def get_full_name(self):
return self.email
def __unicode__(self):
return self.email
class Profile(models.Model):
GENDER = (
('M', 'Homme'),
('F', 'Femme'),
)
user = models.OneToOneField(settings.AUTH_USER_MODEL)
first_name = models.CharField(max_length=120, blank=False)
last_name = models.CharField(max_length=120, blank=False)
gender = models.CharField(max_length=1, choices=GENDER)
zip_code = models.CharField(max_length=5, validators=[MinLengthValidator(5)], blank=False)
def __unicode__(self):
return u'Profile of user: {0}'.format(self.user.email)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
post_save.connect(create_profile, sender=User)
def delete_user(sender, instance=None, **kwargs):
try:
instance.user
except User.DoesNotExist:
pass
else:
instance.user.delete()
post_delete.connect(delete_user, sender=Profile)
Here is my serializers.py这是我的 serializers.py
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('first_name', 'last_name', 'gender', 'zip_code',)
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer(required=True)
class Meta:
model = User
fields = ('url', 'email', 'profile', 'created',)
And here is the views.py这是views.py
class UserList(generics.ListCreateAPIView):
permission_classes = (IsAuthenticatedOrWriteOnly,)
serializer_class = UserSerializer
def get_queryset(self):
if self.request.user.is_staff:
return User.objects.all()
else:
return self.request.user
def post(self, request, format=None):
serializer = ProfileSerializer(data=request.data)
print serializer.__dict__
if serializer.is_valid():
print "valid"
return Response("placeholder", status=status.HTTP_201_CREATED)
My goal is to be able to create the User and the Profile at the same time while being able to valid everything, how could I achieve this ?我的目标是能够同时创建用户和个人资料,同时能够验证所有内容,我怎么能做到这一点?
Indeed, Django Rest Framework can't handle this job with nested relationships then you have to implement these methods yourself.实际上,Django Rest Framework 无法通过嵌套关系处理这项工作,因此您必须自己实现这些方法。 I will give you some example of what your code should look like.
我会给你一些你的代码应该是什么样子的例子。
Your view :你的看法:
class UserList(generics.ListCreateAPIView):
permission_classes = (IsAuthenticatedOrWriteOnly,)
serializer_class = UserSerializer
def post(self, request, format=None):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Now, the save
method of your serializer will call a create
method when you want to create an object and update
method when you want to update an object.现在,您的序列化程序的
save
方法将在您想要创建对象时调用create
方法,并在您想要更新对象时调用update
方法。 So let's implement the create
method of your UserSerializer
which will create the profile and the user.因此,让我们实现
UserSerializer
的create
方法,该方法将创建配置文件和用户。 Here is a simple example of what your UserSerializer
should look like :这是您的
UserSerializer
应该是什么样子的一个简单示例:
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer(required=True)
class Meta:
model = User
fields = ('url', 'email', 'profile', 'created',)
def create(self, validated_data):
# create user
user = User.objects.create(
url = validated_data['url'],
email = validated_data['email'],
# etc ...
)
profile_data = validated_data.pop('profile')
# create profile
profile = Profile.objects.create(
user = user
first_name = profile_data['first_name'],
last_name = profile_data['last_name'],
# etc...
)
return user
As I said, this is an example, you have to complete it to do what you want to do but now, you know how to do it :) To define the behavior during an update, implement an update
method.正如我所说,这是一个例子,你必须完成它才能做你想做的事,但现在,你知道怎么做:) 要定义更新期间的行为,实现一个
update
方法。
This might be late but why not bypass drf entirely and relegate profile creation trigger to models using signals like so:这可能为时已晚,但为什么不完全绕过 drf 并将配置文件创建触发器委托给使用如下信号的模型:
models.py模型.py
class User(AbstractBaseUser):
pass
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='customer_profile')
country = models.CharField(blank=True, max_length=250)
signals.py信号.py
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(
user = instance
)
this basically triggers a corresponding profile row creation once a user has been created via any means;一旦通过任何方式创建了用户,这基本上会触发相应的配置文件行创建; admin, drf etc.
管理员、drf 等
then you can use serializers to update the data.然后您可以使用序列化程序来更新数据。 hope this helps anyone else stumbling here
希望这能帮助其他在这里磕磕绊绊的人
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.