具有 OneToOne 关系的文件的 Django 序列化程序
Django serializer with a filed that has a OneToOne relationship
在我的项目中,我有两个 'types' 用户:客户和企业。它们是来自 django.contrib.auth.models.User
.
的 django 基本用户的扩展
我的 models.py
:
class Customer(models.Model):
user = models.OneToOneField(User, related_name='user', on_delete=models.CASCADE)
birth_date = models.DateField(blank=True, null=True)
phone = PhoneNumberField(unique=True)
def __str__(self):
return self.user.username
class Business(models.Model):
user = models.OneToOneField(User, related_name='business', on_delete=models.CASCADE)
cf = models.CharField(max_length=16, validators=[ssn_validation])
birth_date = models.DateField(null=True)
city = models.CharField(max_length=50, blank=False)
address = models.CharField(max_length=150, blank=False)
好的,那我有两种不同的注册方式,一种用于客户,一种用于企业。
一个问题是,要验证从 REST API 发送的密码,我需要将 password
与 password2
进行比较,创建一个用户(django 基础),并将其传递给我的 Customer.objects.create, 喜欢:
我的 serializers.py
:
class CustomerRegistationSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username',
validators=[UniqueValidator(queryset=User.objects.all())])
email = serializers.CharField(source='user.email',
validators=[UniqueValidator(queryset=User.objects.all())])
first_name = serializers.CharField(source='user.first_name')
last_name = serializers.CharField(source='user.last_name')
password = serializers.CharField(source='user.password', write_only=True)
password2 = serializers.CharField(style={'input_style': 'password'}, write_only=True)
birth_date = serializers.CharField(required=False)
class Meta:
model = Customer
fields = ['id', 'username', 'email', 'password', 'password2', 'first_name', 'last_name',
'birth_date', 'phone']
def save(self):
username = self.validated_data['user']['username']
password = self.validated_data['user']['password']
password2 = self.validated_data['password2']
email = self.validated_data['user']['email']
first_name = self.validated_data['user']['first_name']
last_name = self.validated_data['user']['last_name']
phone = self.validated_data['phone']
try:
birth_date = self.validated_data['birth_date']
except KeyError:
birth_date = None
if password != password2:
raise serializers.ValidationError({'password': 'Passwords must match!'})
user = User.objects.create(username=username, email=email, first_name=first_name, last_name=last_name)
user.set_password(password)
user.is_active = False
user.save()
customer = Customer.objects.create(user=user,
birth_date=birth_date,
phone=phone)
return customer
这确实有效,但如果出现错误,可能会创建用户,但不会创建客户。
是否有更简洁的方式来进行客户注册,始终检查 password == password2
?
编辑: 我找到了一种更优雅的处理方式:
@transaction.atomic
定义保存(自我):
密码 = self.validated_data['user']['password']
密码 2 = self.validated_data['password2']
user = User.objects.create(**self.validated_data['user'])
if password != password2:
raise serializers.ValidationError({'password': 'Passwords must match!'})
user.set_password(password)
user.is_active = False
user.save()
update_last_login(None, user)
del self.validated_data['user']
del self.validated_data['password2']
customer = Customer.objects.create(user=user, **self.validated_data)
return customer
如果你想要求你在 save()
方法中进行的所有数据库事务都成功以有效地将其写入数据库,并且如果在任何时候出现错误则不写入任何内容进程,您通常要求 atomicity(数据库的四种 ACID 功能之一)
使用这个 Django 装饰器,通常是为此而设计的:
from django.db import transaction
@transaction.atomic
def save(self):
<...>
在我的项目中,我有两个 'types' 用户:客户和企业。它们是来自 django.contrib.auth.models.User
.
我的 models.py
:
class Customer(models.Model):
user = models.OneToOneField(User, related_name='user', on_delete=models.CASCADE)
birth_date = models.DateField(blank=True, null=True)
phone = PhoneNumberField(unique=True)
def __str__(self):
return self.user.username
class Business(models.Model):
user = models.OneToOneField(User, related_name='business', on_delete=models.CASCADE)
cf = models.CharField(max_length=16, validators=[ssn_validation])
birth_date = models.DateField(null=True)
city = models.CharField(max_length=50, blank=False)
address = models.CharField(max_length=150, blank=False)
好的,那我有两种不同的注册方式,一种用于客户,一种用于企业。
一个问题是,要验证从 REST API 发送的密码,我需要将 password
与 password2
进行比较,创建一个用户(django 基础),并将其传递给我的 Customer.objects.create, 喜欢:
我的 serializers.py
:
class CustomerRegistationSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username',
validators=[UniqueValidator(queryset=User.objects.all())])
email = serializers.CharField(source='user.email',
validators=[UniqueValidator(queryset=User.objects.all())])
first_name = serializers.CharField(source='user.first_name')
last_name = serializers.CharField(source='user.last_name')
password = serializers.CharField(source='user.password', write_only=True)
password2 = serializers.CharField(style={'input_style': 'password'}, write_only=True)
birth_date = serializers.CharField(required=False)
class Meta:
model = Customer
fields = ['id', 'username', 'email', 'password', 'password2', 'first_name', 'last_name',
'birth_date', 'phone']
def save(self):
username = self.validated_data['user']['username']
password = self.validated_data['user']['password']
password2 = self.validated_data['password2']
email = self.validated_data['user']['email']
first_name = self.validated_data['user']['first_name']
last_name = self.validated_data['user']['last_name']
phone = self.validated_data['phone']
try:
birth_date = self.validated_data['birth_date']
except KeyError:
birth_date = None
if password != password2:
raise serializers.ValidationError({'password': 'Passwords must match!'})
user = User.objects.create(username=username, email=email, first_name=first_name, last_name=last_name)
user.set_password(password)
user.is_active = False
user.save()
customer = Customer.objects.create(user=user,
birth_date=birth_date,
phone=phone)
return customer
这确实有效,但如果出现错误,可能会创建用户,但不会创建客户。
是否有更简洁的方式来进行客户注册,始终检查 password == password2
?
编辑: 我找到了一种更优雅的处理方式:
@transaction.atomic 定义保存(自我): 密码 = self.validated_data['user']['password'] 密码 2 = self.validated_data['password2']
user = User.objects.create(**self.validated_data['user'])
if password != password2:
raise serializers.ValidationError({'password': 'Passwords must match!'})
user.set_password(password)
user.is_active = False
user.save()
update_last_login(None, user)
del self.validated_data['user']
del self.validated_data['password2']
customer = Customer.objects.create(user=user, **self.validated_data)
return customer
如果你想要求你在 save()
方法中进行的所有数据库事务都成功以有效地将其写入数据库,并且如果在任何时候出现错误则不写入任何内容进程,您通常要求 atomicity(数据库的四种 ACID 功能之一)
使用这个 Django 装饰器,通常是为此而设计的:
from django.db import transaction
@transaction.atomic
def save(self):
<...>