I have a a UserProfile model that has a OneToOne with a the
django.contrib.auth User and looks something like this:
class UserProfile(BaseModel):
# Authentication information
email = models.OneToOneField(
User, to_field='username', db_index=True, unique=True,
related_name='profile', on_delete=models.CASCADE
)
I have another model that has a relation to a UserProfile and looks
something like this:
class Something(BaseModel):
user = models.ForeignKey(
'UserProfile', to_field='email', related_name='something',
db_index=True, null=True, on_delete=models.SET_NULL,
)
I have made a custom relational field that looks like this:
class UserProfileField(serializers.RelatedField):
queryset = UserProfile.objects.all()
def to_representation(self, value):
return value.email.username
def to_internal_value(self, data):
try:
return
UserProfile.objects.get(email=User.objects.get(username=data))
except (User.DoesNotExist, UserProfile.DoesNotExist):
raise serializers.ValidationError("User '" + str(data) + "'
does not exist.")
The serializer for Something looks like this:
class SomethingSerializer(serializers.ModelSerializer):
user = UserProfileField(required=True)
class Meta:
model = Something
The idea here is that when sending a request to Something, you should be
able to just do:
{
"user": "[email protected]"
}
rather than:
{
"user": {"email": "[email protected]"}
}
The good news is that this works, the bad news is that it is rife with race
conditions and integrity errors, since the
to_representation/to_internal_value checks aren't done atomically with the
serializer save/create (and take long enough that during testing it's quite
common to run into these race conditions).
Is there a more correct way of achieving that flat serializer
representation, and is this a gross misuse of custom relational fields?
--
You received this message because you are subscribed to the Google Groups
"Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.