使用Django在Model.save()之前执行动作的最佳方法是什么?

时间:2019-07-18 17:47:33

标签: django python-3.x django-rest-framework

我在与React应用程序交互的项目上使用Django-Rest-Framework(ViewSet方法)。因此,我不使用Django admin或Django表单。

我的项目的结构是:

  1. 查看
  2. 序列化器
  3. 模型

我需要做的是在调用模型方法之前执行操作:

  1. 在模型字段中插入request.user。
  2. 在Model.save()之后启动打印机进程
  3. .....

我已经在Django.docs上阅读了很多有关django-way的内容,那里的内容似乎是针对Django-Admin之类的项目显示的,这不是我的情况。

另一方面,通过阅读Stack关于其他主题的答案,这样做的方式似乎是:“它可以工作,但是,这不是正确的方法”。

  1. 根据Django的文档,执行此操作的最佳方法应该是使用名为admin.py的新文件,在该文件中我将注册绑定到Model wich的动作可以支持保存,删除等,但是,不清楚是采用这种方法还是仅提供一种执行操作的Django-Admin方法。
# app/models.py

from django.db import models
from django.contrib.auth.models import User

class Post(models.Model):
    user = models.ForeignKey(User)
    content = models.TextField()

class Comment(models.Model):
    post = models.ForeignKey(Post)
    user = models.ForeignKey(User)
    content = models.TextField()

# app/admin.py

from app.models import Post, Comment
from django.contrib import admin

class CommentInline(admin.TabularInline):
    model = Comment
    fields = ('content',)

class PostAdmin(admin.ModelAdmin):

    fields= ('content',)
    inlines = [CommentInline]

    def save_model(self, request, obj, form, change): 
        obj.user = request.user
        obj.save()

    def save_formset(self, request, form, formset, change): 
        if formset.model == Comment:
            instances = formset.save(commit=False)
            for instance in instances:
                instance.user = request.user
                instance.save()
        else:
            formset.save()

admin.site.register(Post, PostAdmin)

根据我所听到的答案,最好的方法是在Models上使用类似的东西:

class MyModelForm(forms.ModelForm):

   def __init__(self, *args, **kwargs):
       self.request = kwargs.pop('request', None)
       return super(MyModelForm, self).__init__(*args, **kwargs)


   def save(self, *args, **kwargs):
       kwargs['commit']=False
       obj = super(MyModelForm, self).save(*args, **kwargs)
       if self.request:
           obj.user = self.request.user
       obj.save()
       return obj

我想知道的是: 在wich文件中执行该操作的最佳方法是什么,最好的结构是什么。

2 个答案:

答案 0 :(得分:0)

要在“模型”字段上插入request.user,可以在视图类上使用perform_create()方法。有关更多信息,请访问https://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/#associating-snippets-with-users,这正是您想要的!

我不确定启动打印机进程的意思,但是通常可以在保存模型实例后覆盖模型类上的save()方法来进行处理。 https://www.django-rest-framework.org/api-guide/serializers/#overriding-save-directly

答案 1 :(得分:0)

  • 我发现在模型上插入request.user的最佳方法是“ created_by”字段,方法是在模型序列化器上插入具有默认数据的隐藏字段,如下所示:
my_field = serializers.HiddenField(default=serializers.CurrentUserDefault())

CurrentUserDefault()是一个将用户请求返回到序列化程序的函数。

https://www.django-rest-framework.org/api-guide/validators/#advanced-field-defaults

  • 对于在保存/删除之后/之前执行的动作,我选择使用Django Signals,它用作动作的调度程序,有点像react的redux。

https://docs.djangoproject.com/en/2.2/topics/signals/

感谢大家提供有用的答案。