Reputation: 5482
On a project with Django / DRF; I have the following model structure:
class City(models.Model):
name = models.CharField(max_length=100)
class Company(models.Model):
city = models.ForeignKey(City)
.
.
And following serializer structure for Company model:
class CompanySerializer(serializers.ModelSerializer):
city_name = serializers.CharField(write_only=True)
.
.
class Meta:
model = Company
fields = ('city_name',)
def create(self, validated_data):
# Get city
city_name = validated_data.pop('city_name')
try:
city = City.objects.get(name__iexact=city_name)
except City.DoesNotExist:
city = City.objects.create(name=city_name.title())
company = Company.objects.create(city=city, **validated_data)
return company
While creating a company through the serializer, user provides a city_name, I create a new city with that name if not exists or use an existing entry if exists. In this structure, I want to be able to return city_name field while returning companies. It is not a field on the model, so I could use SerializerMethodField normally, but I also want this field to be writable as well. Do I have any options here?
Upvotes: 5
Views: 1498
Reputation: 1554
A better approach is to create two serializer
class CitySerializer(serializers.ModelSerializer):
class Meta:
model = City
fields = ('name')
class CompanySerializer(serializers.ModelSerializer):
city = CitySerializer(write_only=True)
class Meta:
model = Company
fields = ('city',)
def create(self, validated_data):
# Get city
city = validated_data.pop('city')
try:
city = City.objects.get(name__iexact=city)
except City.DoesNotExist:
city = City.objects.create(name=city.title())
company = Company.objects.create(city=city, **validated_data)
return company
Upvotes: 0
Reputation:
i think, your solution is simple to add source and remove write_only
:
city_name = serializers.CharField(source='city.name')
After changing to this approach, you can get city name in create or update methods as follows:
city_data = validated_data.pop('city')
city_name = city_data.get('name')
Upvotes: 1