【问题标题】:What's the best way to perform actions before a Model.save() using Django?在使用 Django 的 Model.save() 之前执行操作的最佳方法是什么?
【发布时间】:2022-02-08 01:39:39
【问题描述】:

我在与 React 应用程序交互的项目中使用 Django-Rest-Framework(ViewSet 方法)。所以,我没有使用 Django 管理员,也没有使用 Django 表单。

我的项目结构是:

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

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

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

我在 Django.docs 上阅读了很多关于 django-way to do 的内容,那里似乎显示了类似 Django-Admin 的项目,这不是我的情况。

另一方面,通过阅读 Stack 在其他主题中的答案,这样做的方式似乎是:“它会起作用,但是,这不是正确的方式”。

  1. 根据 Django 的文档,执行该操作的最佳方法是使用一个名为 admin.py 的新文件,我将在其中注册绑定到可以支持保存、删除等的模型的操作,但是,目前尚不清楚这种方法是要这样做还是仅用于提供 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)

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

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

我想知道的是: 执行该操作的最佳方式是什么,在哪些文件上,最佳结构是什么。

【问题讨论】:

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


    【解决方案1】:

    要在模型字段上插入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

    【讨论】:

    • 谢谢。我的意思是从刚刚保存的模型中打印数据(通过打印机)。
    【解决方案2】:
    • 我发现在模型上插入 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/

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-02
      • 2013-02-10
      • 1970-01-01
      • 2020-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-16
      相关资源
      最近更新 更多