To be more concrete, I'd like to do something like:
user = SlugRelatedField(slug_field=email.username) 

or

user = SlugRelatedField(slug_field=email__username)

where email is the UserProfile field (which is a django User instance) and 
username is the django User username.

On Tuesday, 13 December 2016 15:08:08 UTC-8, Lev Avakian wrote:
>
> SlugRelatedField doesn't quite do what I need. While I can serialize to 
> the field, when deserializing it still needs to_internal_value to be 
> overridden, so I am essentially back to my Custom Relational Field. 
>
> Here's an example of a race condition. I post to Something with "
> [email protected]" as my user field. The custom field does a get and 
> finds a User with that email as the username, and then it does a get for a 
> UserProfile with that User. So far so good, we've converted the string to a 
> UserProfile instance, but, right after that, the User with 
> [email protected] as the username (and the associated UserProfile) are 
> deleted, so when the Something serializer tries to save or update, it runs 
> into an internal server error since that User/UserProfile no longer exists. 
> I'm trying to figure out what the best way to make this process atomic or 
> what the proper field type is for this kind of relation.
>
> On Tuesday, 13 December 2016 14:31:24 UTC-8, Xavier Ordoquy wrote:
>>
>>
>> Le 13 déc. 2016 à 20:58, Lev Avakian <[email protected]> a écrit :
>>
>> 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?
>>
>>
>> Hi,
>>
>> You’re probably looking at the SlugRelatedField (
>> http://www.django-rest-framework.org/api-guide/relations/#slugrelatedfield
>> )
>> Not sure what you mean when you mention your race condition and integrity 
>> errors. Could you be more explicit about them ?
>>
>> Regards,
>> Xavier,
>> Linovia.
>>
>>

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

Reply via email to