2017-05-26 71 views
1

我有任務模式:創建對象時,自動創建標籤對象,Django的REST框架

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') 

和類任務類型(即標籤):

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

我也有TaskSerializer:

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') 

當我創建一個任務,要添加一些標籤,我需要在相應的視圖中創建它們首先,但我希望它們在飛行中被創建。 所以在編輯任務的情況下,我加入update方法:

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) 

它工作正常,但是當我創建失敗了新的任務(400錯誤的請求)時,加入新的標籤:

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

我想通了,這將是它在創建任務之前創建相應的標記對象的好辦法,所以我加了perform_create方法:

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) 

它並沒有幫助我,實際上我不確定是否至少調用了perform_create方法,因爲我在控制檯中看不到任何打印('debug')(當我使用現有標記創建Task時,我發現它)。 所以問題是如何更改perform_create方法,以便無需首先創建標籤即可創建新的任務。

回答

0

嘗試編輯您的看法是這樣,

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

基本上你的方法是編輯任務(put方法),我需要在創建新的任務時指定新的標籤。 –

+0

你在想如何指定標籤?你是否通過request.data ['tags']發送了tag_names?我不太明白你的要求是什麼.. – zaidfazil

+0

我發送POST到任務視圖是這樣的:{「tags」:[「tag1」,「tag2」,...],「name」:「name」,.. 。} –

1

首先,你並不需要在您的視圖方式手動add標籤。序列化程序將爲您完成。

二,當您的更新您的模型時使用update方法。當創建你需要重寫create方法,perform_create工作,但會發生爲時已晚:

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) 

第三,一旦你創建新的標籤,請致電super().*method*並讓框架做的工作適合你:

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) 

還有partial_update方法,你需要,如果你打算使用PATCH方法來添加,所以你可能會更好重寫你的串行的to_internal_value方法,而不是每個那些的:

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

謝謝!我設法解決這個添加create()方法。 –