2016-08-17 3 views
4

In meinem Modelle, habe ich die folgenden Klassen:Posting eine Fremdschlüsselbeziehung in Django Rastrahmen

class Topic(models.Model): 
    name = models.CharField(max_length=25, unique=True) 

class Content(models.Model): 
    title = models.CharField(max_length=255) 
    body = models.TextField() 
    topic = models.ForeignKey(Topic, blank=True, null=True) 

Mein Serializer ist wie folgt:

class TopicSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Topic 
     fields = ('name') 

class ContentSerializer(serializers.ModelSerializer): 
    topic = TopicSerializer(read_only=True) 
    class Meta: 
      model = Content 
      fields = ('title', 'body', 'topic') 

Okay, so in Meine URLs Datei, ich habe das folgende Muster:

urlpatterns = [ 
    ... 
    url(r'^api/topic_detail/(?P<name>[a-zA-Z0-9-]+)/content_list/$', views.topic_content_list, name='topic_content_list'), 
    ... 
] 

Daher, wenn der Benutzer geht zu sagen /api/topic_detail/sports/content_list/, erhalten wir eine Liste aller Inhalte, die das Thema Sport hat. Nun, was ich will ist, wenn wir POST die folgenden Daten an die obige URL, dann ein Content-Objekt mit dem Thema Feld automatisch mit Sport verbunden erstellt.

Ich versuche, diese die folgende Art und Weise in meinen Ansichten zu tun:

@api_view(['GET', 'POST']) 
def topic_content_list(request, name): 
    try: 
     topic = Topic.objects.get(name=name) 
    except: 
     return Response(status=status.HTTP_404_NOT_FOUND) 

    if request.method == 'GET': 
     contents = Content.objects.filter(topic=topic) 
     serializer = ContentSerializer(contents, many=True) 
     return Response(serializer.data) 

    elif request.method == 'POST': 
     request.data["topic"] = topic 
     serializer = ContentSerializer(data=request.data) 
     print request.data 
     if serializer.is_valid(): 
      serializer.save() 
      return Response(serializer.data, status=status.HTTP_201_CREATED) 
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 

Jetzt kann sagen, dass ich gehe die URL /api/topic_detail/sports/content_list/ und POST dies:

{ 
    "title": "My blog post", 
    "body" : ".....", 
} 

Das Content-Objekt erstellt wird, und das Titel- und Körperfeld ist richtig eingestellt. Das Themenfeld ist jedoch auf Null festgelegt. Wie kann ich das beheben? Jede Hilfe wird geschätzt.

Auch, bitte nicht vorschlagen generische Viewsets, wie ich bin unangenehm mit so viele Dinge passiert automatisch.

EDIT

Okay, so meine dummen Fehler, den ich festgelegt:

class ContentSerializer(serializers.ModelSerializer): 
    topic = TopicSerializer(read_only=False) 
    class Meta: 
      model = Content 
      fields = ('title', 'body', 'topic') 

Das heißt, ich die read_only Argument auf False. Doch jetzt schafft die Post einen neuen Fehler:

{ 
    "topic": { 
     "non_field_errors": [ 
      "Invalid data. Expected a dictionary, but got Topic." 
     ] 
    } 
} 

Dieses Ich bin mir ziemlich sicher auf die Tatsache bezieht, dass die data.website ich bin das Senden ist nicht JSON, sondern nur ein Django-Modell-Instanz. Wie kann ich die einzelne Instanz JSONifizieren?

Antwort

4

Dies ist von Ihrem Serializer.

 topic = TopicSerializer(read_only=True) 

Es bedeutet, dass Ihr Thema nur so gelesen wird, wenn Sie versuchen, Ihre Serializer zu speichern, wird Thema nicht gespeichert zu werden. Entfernen Sie das und das Problem wurde behoben.

EDIT:

nun nach dem zweiten Fehler, es ist, weil es eine dict erwartet und Sie die Modellinstanz sind vorbei, so haben Sie zwei Möglichkeiten. Entweder erstellen Sie das Diktat von Hand.

topic_dict = { "name": topic.name }

und übergeben, die als 'Thema' in Anfrage.Daten und dann speichern oder geben Sie die topic_id, da es eine Fremdschlüsselbeziehung ist, sollte es funktionieren.

So wäre es so etwas wie:

request.data["topic_id"] = topic.id 

Was nun wählen Sie ist total bis zu Ihnen zu tun.

+0

Vielen Dank. Ich habe eine Bearbeitung hinzugefügt, können Sie mir helfen? –

+0

Nvm, ich sollte eine andere Frage stellen, da das Problem ein anderes ist. –

+0

Nur meine Antwort aktualisiert. –

Verwandte Themen