Rozwiązałem ten problem w nieco inny sposób.
Zastosowanie:
- DRF 3.5.x
- django-modelu-utils 2.5.x
Moja models.py
wyglądać następująco:
class Person(models.Model):
first_name = models.CharField(max_length=40, blank=False, null=False)
middle_name = models.CharField(max_length=80, blank=True, null=True)
last_name = models.CharField(max_length=80, blank=False, null=False)
family = models.ForeignKey(Family, blank=True, null=True)
class Clergy(Person):
category = models.IntegerField(choices=CATEGORY, blank=True, null=True)
external = models.NullBooleanField(default=False, null=True)
clergy_status = models.ForeignKey(ClergyStatus, related_name="%(class)s_status", blank=True, null=True)
class Religious(Person):
religious_order = models.ForeignKey(ReligiousOrder, blank=True, null=True)
major_superior = models.ForeignKey(Person, blank=True, null=True, related_name="%(class)s_superior")
class ReligiousOrder(models.Model):
name = models.CharField(max_length=255, blank=False, null=False)
initials = models.CharField(max_length=20, blank=False, null=False)
class ClergyStatus(models.Model):
display_name = models.CharField(max_length=255, blank=True, null=True)
description = models.CharField(max_length=255, blank=True, null=True)
Zasadniczo - podstawę model jest modelem "osoby" - a osoba może być duchowną, zakonnicą lub żadną z nich i po prostu być "Osoba". Modele dziedziczące Person
również mają specjalne relacje.
W moim views.py
I wykorzystują wstawek „wstrzyknięcie” podklasy do queryset tak:
class PersonSubClassFieldsMixin(object):
def get_queryset(self):
return Person.objects.select_subclasses()
class RetrievePersonAPIView(PersonSubClassFieldsMixin, generics.RetrieveDestroyAPIView):
serializer_class = PersonListSerializer
...
a następnie prawdziwy „unDRY” część jest w serializers.py
gdzie mogę zadeklarować „baza” PersonListSerializer, ale zastąpić metodę to_representation
powrotu specjalne serailzers oparciu o typ przykład tak:
class PersonListSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
if isinstance(instance, Clergy):
return ClergySerializer(instance=instance).data
elif isinstance(instance, Religious):
return ReligiousSerializer(instance=instance).data
else:
return LaySerializer(instance=instance).data
class Meta:
model = Person
fields = '__all__'
class ReligiousSerializer(serializers.ModelSerializer):
class Meta:
model = Religious
fields = '__all__'
depth = 2
class LaySerializer(serializers.ModelSerializer):
class Meta:
model = Person
fields = '__all__'
class ClergySerializer(serializers.ModelSerializer):
class Meta:
model = Clergy
fields = '__all__'
depth = 2
„switch” to miejsce w metodzie głównego serializatora to_representation
(PersonListSerializer
). Sprawdza typ instancji, a następnie "wstrzykuje" potrzebny serializator. Od Clergy
, Religious
są dziedziczone po Person
, otrzymując z powrotem Person
, który jest także członkiem Clergy
, zwraca wszystkie pola Person
i wszystkie pola Clergy
. To samo dotyczy Religious
. A jeśli Person
nie jest ani Clergy
ani Religious
- pola modelu podstawowego są zwracane.
Nie jestem pewien, czy to właściwe podejście, ale wydaje się bardzo elastyczne i pasuje do mojego zastosowania. Zauważ, że zapisuję/aktualizuję/tworzę Person
przez różne widoki/serializery - więc nie muszę się o to martwić tym typem instalacji.
http://www.django-rest-framework.org/topics/3.0-announcement/#changes-to-the-custom-field-api –
czy znalazłeś już lepsze rozwiązanie? – eugene