Ich habe ein AngularJS-Projekt, das Django als Framework über das Django Rest Framework (DRF) verwendet.Django Rest Framework Viele zu viele Feld bezogen auf sich selbst
Ich habe ein Gruppenmodell erstellt und eine Serialisierungsklasse dafür eingerichtet, möchte jedoch jetzt ein neues Feld für dieses Modell namens related_groups
einrichten, das auf dasselbe Modell (Gruppe) verweist wie ein Array von Primärschlüsseln .
Ich weiß nicht, ob es möglich ist, im Serialisierer selbst zu referenzieren, und ich weiß nicht, wie sonst verwandte Gruppen vom Front-End, die von den Benutzern ausgewählt und ausgewählt werden können Wer besitzt die Gruppe? Ich möchte, dass dieses Feld die Primärschlüssel anderer Gruppenzeilen referenziert und durch diese Sammlung von Gruppen iteriert, um eine verwandte Gruppenbeziehung herzustellen.
class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = mod.Group
fields = (
'group_id',
'group_name',
'category',
'related_groups',
)
und die Darstellung erscheint genau das zu sein, was ich will:
GroupSerializer():
group_id = IntegerField(read_only=True)
group_name = CharField(max_length=100)
category = CharField(max_length=256, required=False
related_groups = PrimaryKeyRelatedField(many=True, queryset=Group.objects.all(), required=False)
und das Modell wird als solche dargestellt werden:
class Group(models.Model):
"""
Model definition of a Group. Groups are a collection of users (i.e.
Contacts) that share access to a collection of objects (e.g. Shipments).
"""
group_id = models.AutoField(primary_key=True)
group_name = models.CharField(max_length=100)
owner_id = models.ForeignKey('Owner', related_name='groups')
category = models.CharField(max_length=256)
related_groups = models.ManyToManyField('self', blank=True, null=True)
history = HistoricalRecords()
def __unicode__(self):
return u'%s' % (self.group_name)
def __str__(self):
return '%s' % (self.group_name)
Der Blick dieses Modell den Zugriff auf ziemlich einfache CRUD Ansicht ist :
@api_view(['GET', 'PUT', 'DELETE'])
@authentication_classes((SessionAuthentication, BasicAuthentication))
@permission_classes((IsAuthenticated, HasGroupAccess))
def group_detail(request, pk, format=None):
group, error = utils.get_by_pk(pk, mod.Group, request.user)
if error is not None:
return error
if request.method == 'GET':
serializer = ser.GroupSerializer(group)
return Response(serializer.data)
elif request.method == 'PUT':
return utils.update_object_by_pk(request, pk, mod.Group,
ser.GroupSerializer)
elif request.method == 'DELETE':
return utils.delete_object_by_pk(request.user, pk, mod.Group)
denen einige Hygienisierung und Validierungsmethoden ruft:
def update_object_by_pk(request, pk, obj_type, serializer):
try:
with transaction.atomic():
obj, error = select_for_update_by_pk(pk, obj_type, request.user)
if error is not None:
return error
obj_serializer = serializer(obj, data=request.data)
if obj_serializer.is_valid():
obj_serializer.save()
else:
response = ("Attempt to serialize {} with id {} failed "
"with errors {}").format(str(obj_type), str(pk),
str(serializer.errors))
return Response(response, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
response = ("Error attempting to update {} with ID={}. user={}, "
"error={}".format(str(obj_type), str(pk),
str(request.user.email), str(e)))
return Response(response, status=status.HTTP_400_BAD_REQUEST)
else:
resp_str = ("Successfully updated {} with ID={}".format(str(obj_type),
str(pk)))
return Response(resp_str, status=status.HTTP_200_OK)
die Anrufe:
def select_for_update_by_pk(pk, mod_type, user):
response = None
obj = None
try:
obj = mod_type.objects.select_for_update().get(pk=pk)
except mod_type.DoesNotExist:
resp_str = ("{} could not be found with ID={}.".
format(str(mod_type), str(pk)))
response = Response(resp_str, status=status.HTTP_404_NOT_FOUND)
return obj, response
die nur ein Wrapper um select_for_update()
Django Methode.
Die Migration erstellte eine neue Tabelle namens group_related_groups mit einer ID, einer from_group- und einer to_group-Spalte, die von Django als Junction/Lookup verwendet wird, um diese Beziehungen herzustellen.
Ich kann einzeln auf diesen Endpunkt schreiben, aber der Serializer GroupSerializer scheint standardmäßig nicht mehrere Werte zulassen zu wollen.
Es ist also erfolgreich, eine PUT-Anforderung zum PUT zu verwenden, um einen Wert von '2' für die Gruppierung mit einem PK von 1 zu erhalten. Allerdings versucht ['2','3']
, [2,3]
, 2,3
und '2','3'
es zurück durch den Blick auf eine Hilfsmethode zu setzen Tracing, ich sehe, dass es serializer.is_valid()
die Anforderung fehlgeschlagen ist, so dass macht mich denke, es ist ein many=True
Thema, aber ich don‘ Sie wissen, welche Beziehung Serializer für dieses spezielle selbstreferenzielle ManyToManyField-Problem verwenden soll.
Beim Debuggen, ich bin zum Ausgeben des serializer.is_valid() Fehler wie diese syslog:
response = ("Attempt to serialize {} with id {} failed "
"with errors {}").format(str(obj_type), str(pk),
str(serializer.errors))
logger.exception(response)
Und ich bin immer diese Ausnahme Meldung als Antwort:
Message: "Attempt to serialize <class 'bioapi.models.Group'> with id 1 failed with errors
"
Die Debugfehlerausgabe für obj_serializer.Fehler ist
obj_serializer.error of {'related_groups': ['Incorrect type. Expected pk value, received str.']}
Und hier ist debug messasge auf request.data:
{'group_name': 'Default Guest Group', 'related_groups': [1], 'group_id': 2, 'category': 'guest'}
, die erfolgreich ist, und
<QueryDict: {'group_name': ['requestomatic'], 'related_groups':['2,2'], category': ['guest']}>
was fehlschlägt. Wenn ich mir das jetzt anschaue, frage ich mich, ob Postman-Formulardaten das Problem darstellen. Wenn das der Fall ist, werde ich mich ziemlich dumm fühlen.
Kann ich viele-zu-viele-Beziehungen von einem Modell zu sich selbst mit DRF darstellen, oder muss ich einen benutzerdefinierten Serializer nur für die Beziehungstabelle haben? Die Dokumentation für DRF verwendet keine selbstreferentiellen Modelle und alle Beispiele, die ich online finde, verwenden entweder mehrere Modelle oder mehrere Serialisierer.
Ist es möglich, ManyToManyField in meinem Modell zu verwenden, das mit dem Django Rest Framework (DRF) und seinen Serialisierern selbstreferenziell ist? Wenn das so ist, wie?
bitte erklären, was Sie 'GroupSerializer bedeuten() : 'in Ihrem zweiten Ausschnitt – e4c5
Sobald' serializer.is_valid() 'fehlgeschlagen ist, was ist der Inhalt von' serializer.errors'? Es gibt normalerweise gute Hinweise, warum es versagt. –
@ e4c5, Überprüfung der Serializer-Beziehung mit der Methode beschrieben in der Serializer Relationen Dokumentation, hier: http://www.django-rest-framework.org/api-guide/relations/#inspecting-relationships, und die Beziehung scheint zu geordnet sein. – Smittles