Как сделать поле StringRelatedField, доступное только для чтения и объявленное как ForeignKey, доступным для пост-запросов?
У меня есть следующие два класса моделей в django rest framework
class Customer(models.Model):
GENDER_CHOICES = [
('Male', 'Male'),
('Female', 'Female'),
]
customer_id = models.AutoField(primary_key=True)
firstname = models.CharField(max_length=20)
lastname = models.CharField(max_length=30)
gender = models.CharField(max_length=6, choices=GENDER_CHOICES)
date_of_birth = models.DateField()
nationality = models.CharField(max_length=50, null=False)
id_card_number = models.CharField(max_length=20, unique=True)
passport_number = models.CharField(max_length=20, unique=True)
address = models.CharField(max_length=100)
phone_number = models.CharField(max_length=20)
email = models.EmailField(max_length=254,null=True, blank=True, unique=True)
def __str__(self):
return f"{self.firstname} {self.lastname}"
class Contract(models.Model):
INSURANCE_TYPE_CHOICES = [
('Health', 'Health Insurance'),
('Life', 'Life Insurance'),
('Auto', 'Auto Insurance'),
('Home', 'Home Insurance'),
]
contract_number = models.AutoField(primary_key=True)
start_date = models.DateField()
end_date = models.DateField()
insurance_type = models.CharField(max_length=15, choices=INSURANCE_TYPE_CHOICES)
insurance_holder = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="contracts")
active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.contract_number} {self.insurance_type}"
и следующие два сериализатора
class ContractSerializer(serializers.ModelSerializer):
insurance_holder = serializers.StringRelatedField(read_only=True)
class Meta:
model = Contract
exclude = ("updated_at",)
class CustomerSerializer(serializers.ModelSerializer):
contracts = ContractSerializer(many=True, read_only=True)
class Meta:
model = Customer
fields = "__all__"
Я также создал свои конечные точки url и представления, я протестировал свой api через Postman и встроенный django-rest browasable API и все в порядке, но у меня возникла следующая проблема.
Держатель страховки является внешним ключом моей модели клиентов, поэтому, когда я получаю запросы в конечной точке контрактов, я получаю Id вместо полного имени, поэтому я установил держателя страховки в сериализаторе как StringRelatedField, чтобы получить полное имя, однако это поле только для чтения, поэтому я не могу отправлять запросы в контракты с полным именем. Как я могу сделать пост-запросы с именем, но сохранить ограничение внешнего ключа моделей.
Кстати, я новичок в Django и Django Rest Framework, да и вообще новичок.
Я уже прочитал документацию django rest о связанных полях и следующий пост stack overflow Как я могу показать StringRelatedField вместо Primary Key, сохраняя возможность записи в это поле с помощью Django Rest Framework? но я все еще не понимаю, как решить эту проблему.
Самым простым решением будет переопределить to_representation
метод сериализации сериализатора и заменить возвращаемое значение, не изменяя исходное поле:
class ContractSerializer(serializers.ModelSerializer):
class Meta:
model = Contract
exclude = ("updated_at",)
def to_representation(self, instance):
representation = super().to_representation(instance)
representation["insurance_holder"] = str(instance.insurance_holder)
return representation