2017-08-28 153 views
1

簡介:覆蓋在Django的ModelForm保存()方法來創建或更新

我要重寫保存()方法,在我的自定義的ModelForm在模型中創建一個新的行或更新一些數據如果它存在。我已經找到了一些解決方案,但它在視圖函數中實現,如鏈接Django form INSERTs when I want it to UPDATE,但我想以save()方法實現它。

我的模型:

我默認auth.User型號和我的作者模型,如下圖所示,我也有另一種模式叫UserAuthor,用於當它們之間的多對多關係在我的情況下強制要求添加其他領域,如「is_follow」和「審查」

class Author(models.Model): 
    name = models.CharField(max_length=50) 

class UserAuthor(models.Model): 
     user = models.ForeignKey(User, on_delete=models.CASCADE) 
     author = models.ForeignKey(Author, on_delete=models.CASCADE) 
     is_follow = models.BooleanField(default=0) 
     review = models.TextField(max_length=500, blank=True, null=True) 

我的表格:

class ReviewFollowAuthorForm(forms.ModelForm): 
    class Meta: 
     model = UserAuthor 
     fields = ("is_follow", "review") 

    def save(self, commit=True, user=None, author=None): 
     user_author = super(ReviewFollowAuthorForm, self).save(commit=False) 
     user_author.user = user 
     user_author.author = author 
     if commit: 
      user_author.save() 
     return user_author 

筆者認爲:

class ReviewFollowAuthor(View): 
    def post(self, request, **kwargs): 
     user = request.user 
     author = get_object_or_404(Author, id=kwargs['pk']) 
     f = ReviewFollowAuthorForm(request.POST) 
     if(f.is_valid()): 
      f.save(user=user,userx=userx) 
      return JsonResponse({'success':1}) 
     else: 
      return JsonResponse({'success':0}) 

在這種情況下,它在數據庫中爲每個保存()調用創建一個新的行。我不知道如何在保存之前檢查save方法,只需更新以防在請求者用戶的前一行有作者,我嘗試了許多事情,但是我失敗了。我知道我可以使用:

user_author = UserAuthor.objects.filter(user=user, author=author) 

和更新,如果它返回一個結果,但在save()方法本身怎麼樣?

回答

1

使用django queryset get_or_create()方法。

來自文檔:該方法用於查找具有給定kwargs的對象(如果模型具有所有字段的默認值,則可能爲空),如果需要則創建一個。

瞭解更多關於它here in the docs。現在

,您的視圖中:現在

class ReviewFollowAuthor(View): 
    def post(self, request, **kwargs): 
     user = request.user 
     author = get_object_or_404(Author, id=kwargs['pk']) 
     #MAKE certain that user and author always have an instance within them. 
     #send the user, author to the form. 
     f = ReviewFollowAuthorForm(request.POST , user = user , author = author) 
     if(f.is_valid()): 
      f.save(user=user,userx=userx) 
      return JsonResponse({'success':1}) 
     else: 
      return JsonResponse({'success':0}) 

,您的ModelForm中:

class ReviewFollowAuthorForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     #override __init__ to make your "self" object have the instances sent by the your views.(author and user) 
     self.user = kwargs.pop('user' , None) 
     self.author = kwargs.pop('author' , None) 
     #Now your model-form instance has the user and the author attribute within itself. 
     super(ReviewFollowAuthorForm, self).__init__(*args, **kwargs) 
    class Meta: 
     model = UserAuthor 
     fields = ("is_follow", "review") 

    def save(self, commit=True): 
     user_author, created = UserAuthor.objects.update_or_create(user=self.user, author=self.author, defaults={'is_follow': self.cleaned_data.get('is_follow'), 'review': self.cleaned_data.get('review')}) 
     #rest of your logic 
     return user_author 

我希望這會引導你以某種方式。 謝謝。

+0

對不起,但我感到困惑與你的答案。你說我可以使用'get_or_create()'但是在哪裏?此外,在「除外」情況下,將使用POST請求正文中的額外字段創建新記錄。很好,但在「嘗試」的情況下,如何更新user_author的字段而不單獨從請求主體獲取字段? –

+0

@yassermohsen我已經更新了我的答案,並試圖做得更詳細一些。請檢查一下。 –

+0

它正在工作,謝謝。但是我更新了你的代碼,並且使用'defaults'屬性的'update_or_create()'方法更容易更新字段。 'def save(self,commit = True): user_author,created = UserAuthor.objects.update_or_create( user = self.user,author = self.author, defaults = {'is_follow':self.cleaned_data.get 'is_follow'),'review':self.cleaned_data.get('review')} ) return userxuser' 請在您的回答中更新它以便其他人清楚,並從保存中刪除用戶和作者()方法參數 –