2017-05-26 6 views
1

zu schaffen habe ich die Aufgabe Modell:automatisch Tag-Objekte erstellen, wenn ein Objekt, Django REST-Framework

class Task(models.Model): 
    name = models.CharField(max_length=200, blank=True) 
    description = models.TextField(max_length=1000, blank=True) 
    completed = models.BooleanField(default=False) 
    date_created = models.DateField(auto_now_add=True) 
    due_date = models.DateField(null=True, blank=True) 
    date_modified = models.DateField(auto_now=True) 
    tasklist = models.ForeignKey(Tasklist, null=True, related_name='tasks', on_delete=models.CASCADE) 
    tags = models.ManyToManyField(TaskType, related_name='tasks') 

und Klasse Tasktype (tag mit anderen Worten):

class TaskType(models.Model): 
    name = models.CharField(max_length=200) 

Ich habe auch TaskSerializer:

Wenn ich eine Aufgabe erstellen, um einige Tags hinzuzufügen, muss ich sie zuerst in der entsprechenden Ansicht erstellen, aber ich möchte, dass sie spontan erstellt werden. So im Falle der Aufgabe bearbeiten, habe ich update Methode:

def update(self, request, *args, **kwargs): 
    instance = self.get_object() 
    tag_names = request.data.get('tags', []) 
    for tag_name in tag_names: 
     tag, created = TaskType.objects.get_or_create(name=tag_name) 
     instance.tags.add(tag) 

    serializer = self.serializer_class(instance=instance, data=request.data) 
    serializer.is_valid(raise_exception=True) 
    serializer.save() 
    return Response(serializer.data) 

Es funktioniert gut, aber wenn ich hinzufügen, neue Tags, wenn Erstellen einer neuen Aufgabe es (400 Bad Request) ausfällt:

{ 
    "tags": [ 
     "Object with name=%new_tag% does not exist." 
    ] 
} 

ich finde heraus, dass es ein guter Weg sein würde, damit vor dem erstellen Aufgabe entsprechendes Tag-Objekt zu erstellen, so dass ich hinzugefügt perform_create Methode:

def perform_create(self, serializer): 
    print('debug') 
    tag_names = self.request.data.get('tags', []) 
    for tag_name in tag_names: 
     tag, created = TaskType.objects.get_or_create(name=tag_name) 

    list_id = self.kwargs.get('list_id', None) 
    try: 
     tasklist = Tasklist.objects.get(pk=list_id) 
    except Tasklist.DoesNotExist: 
     raise NotFound() 
    serializer.save(tasklist=tasklist) 

Es hilft mir nicht, eigentlich bin ich mir nicht sicher, ob die perform_create-Methode zumindest aufgerufen wird, weil ich in der Konsole keinen Ausdruck ('debug') sehe (wenn ich Task mit einem vorhandenen Tag erzeuge, sehe ich es). Die Frage ist also, wie man die Methode perform_create ändert, um neue Aufgaben erstellen zu können, ohne zuerst das Tag zu erstellen.

Antwort

0

Versuchen Sie, Ihre Ansicht wie diese Bearbeitung,

def update(self, request, *args, **kwargs): 
    instance = self.get_object() 
    tag_names = request.data.get('tags', []) 
    serializer = self.serializer_class(instance=instance, data=request.data) 
    if serializer.is_valid(raise_exception=True) 
     new_object = serializer.save() 
    if new_object: 
     for tag_name in tag_names: 
      tag, created = TaskType.objects.get_or_create(name=tag_name) 
      new_object.tags.add(tag) 
    return Response(serializer.data) 
+0

Grundsätzlich ist Ihre Methode zum Bearbeiten der Aufgabe (put-Methode), ich muss neue Tags beim Erstellen neuer Aufgabe angeben. –

+0

Wie denkst du, die Tags zu spezifizieren? Schicken Sie die tag_names über request.data ['tags'] ?? Ich verstehe nicht ganz, was Ihre Anforderung ist .. – zaidfazil

+0

Ich sende POST zu einer Task-Ansicht wie folgt: {"Tags": ["Tag1", "Tag2", ...], "Name": "Name", .. .} –

1

Zuerst Sie manuell add Tags Ihrer Ansicht nach Methoden, um nicht brauchen. Der Serializer wird es für Sie tun.

Zweitens wird die update Methode verwendet, wenn Sie aktualisieren Ihr Modell. Wenn Erstellung benötigen Sie create Methode, perform_create Werke außer Kraft zu setzen, aber passiert, zu spät:

def create(self, request, *args, **kwargs): 
    tag_names = request.data.get('tags', []) 
    for tag_name in tag_names: 
     TaskType.objects.get_or_create(name=tag_name) 

    serializer = self.serializer_class(data=request.data) 
    serializer.is_valid(raise_exception=True) 
    serializer.save() 
    return Response(serializer.data) 

Drittens, wenn Sie neue Tags erstellt haben, super().*method* rufen und lassen Sie den Rahmen machen die Arbeit für Sie:

def update(self, request, *args, **kwargs): 
    tag_names = request.data.get('tags', []) 
    for tag_name in tag_names: 
     TaskType.objects.get_or_create(name=tag_name) 

    return super().update(request, *args, **kwargs) 

def create(self, request, *args, **kwargs): 
    tag_names = request.data.get('tags', []) 
    for tag_name in tag_names: 
     TaskType.objects.get_or_create(name=tag_name) 

    return super().create(request, *args, **kwargs) 

Es gibt auch partial_update Methode, die Sie hinzufügen müssen, wenn Sie PATCH Methode verwenden möchten, so können Sie besser dran, Ihre Serializer oberstes to_internal_value Methode anstelle jedes dieser:

class TaskSerializer(serializers.ModelSerializer): 
    tags = serializers.SlugRelatedField(
     many=True, slug_field='name', queryset=TaskType.objects.all()) 

    class Meta: 
     model = Task 
     fields = '__all__' 
     read_only_fields = ('date_created', 'date_modified', 'tasklist') 

    def to_internal_value(self, data): 
     for tag_name in data.get('tags', []): 
      TaskType.objects.get_or_create(name=tag_name) 
     return super().to_internal_value(data) 
+0

Danke! Ich habe es geschafft, diese create() -Methode zu lösen. –

Verwandte Themen