Mam pytanie dotyczące obsługi modeli m2m / through i ich prezentacji w frameworku django rest. Weźmy klasyczny przykład:
models.py:
from django.db import models
class Member(models.Model):
name = models.CharField(max_length = 20)
groups = models.ManyToManyField('Group', through = 'Membership')
class Group(models.Model):
name = models.CharField(max_length = 20)
class Membership(models.Model):
member = models.ForeignKey('Member')
group = models.ForeignKey('Group')
join_date = models.DateTimeField()
serializers.py:
imports...
class MemberSerializer(ModelSerializer):
class Meta:
model = Member
class GroupSerializer(ModelSerializer):
class Meta:
model = Group
views.py:
imports...
class MemberViewSet(ModelViewSet):
queryset = Member.objects.all()
serializer_class = MemberSerializer
class GroupViewSet(ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
UZYSKUJĄC instancję członka pomyślnie otrzymuję wszystkie pola członka, a także jego grupy - jednak otrzymuję tylko szczegóły grup, bez dodatkowych szczegółów pochodzących z modelu członkostwa.
Innymi słowy, oczekuję, że otrzymam:
{
'id' : 2,
'name' : 'some member',
'groups' : [
{
'id' : 55,
'name' : 'group 1'
'join_date' : 34151564
},
{
'id' : 56,
'name' : 'group 2'
'join_date' : 11200299
}
]
}
Zwróć uwagę na join_date .
Wypróbowałem tak wiele rozwiązań, w tym oczywiście oficjalną stronę Django Rest-Framework na ten temat i nikt nie wydaje się udzielić właściwej, prostej odpowiedzi na ten temat - co mam zrobić, aby uwzględnić te dodatkowe pola? Wydało mi się to prostsze dzięki django-tastypie, ale miałem kilka innych problemów i wolę rest-framework.
Odpowiedzi:
Co powiesz na.....
W swoim MemberSerializerze zdefiniuj na nim pole, takie jak:
a następnie w swoim serializatorze członkostwa możesz utworzyć to:
Ma to ogólny wpływ na utworzenie serializowanej wartości, grup, których źródłem jest pożądane członkostwo, a następnie używa niestandardowego serializatora do wyciągnięcia bitów, które chcesz wyświetlić.
EDYCJA: jak skomentował @bryanph, w DRF 3.0
serializers.field
zmieniono nazwę naserializers.ReadOnlyField
, więc powinno to brzmieć:do wszelkich nowoczesnych realizacji
źródło
membership_set
jest domyślną nazwą pokrewną dla Członka -> CzłonkostwoMiałem do czynienia z tym problemem i moim rozwiązaniem (przy użyciu DRF 3.6) było użycie SerializerMethodField na obiekcie i jawne zapytanie do tabeli członkostwa w następujący sposób:
Spowoduje to zwrócenie listy dykt dla klucza grup, w którym każdy dykt jest serializowany z MembershipSerializer. Aby umożliwić zapis, możesz zdefiniować własną metodę tworzenia / aktualizacji w ramach MemberSerializer, w której iterujesz dane wejściowe i jawnie tworzysz lub aktualizujesz wystąpienia modelu członkostwa.
źródło
UWAGA: Jako inżynier oprogramowania uwielbiam korzystać z architektur i głęboko pracowałem nad warstwowym podejściem do programowania, więc będę odpowiadać na to z szacunkiem dla poziomów.
Jak zrozumiałem problem, oto rozwiązanie models.py
serializers.py
CustomModels.py
BusinessLogic.py
Technicznie rzecz biorąc, musiałbyś przekazać żądanie do DataAccessLayer, który zwróciłby filtrowane obiekty z warstwy dostępu do danych, ale ponieważ muszę odpowiedzieć na pytanie w szybki sposób, dostosowałem kod w warstwie logiki biznesowej!
źródło