如何在Django中创建和使用信号

如何在Django中创建和使用信号

信号被用来执行任何关于修改模型实例的行动。信号是帮助我们将事件与行动联系起来的工具。我们可以开发一个函数,当一个信号调用它时,它就会运行。换句话说,信号被用来在数据库中修改/创建一个特定的条目时执行一些动作。例如,人们希望在数据库中创建一个新的用户实例时,立即创建一个配置文件实例。

有3种类型的信号。

  1. pre_save/post_save : 这个信号在save()方法之前/之后发挥作用。
  2. pre_delete/post_delete : 这个信号在删除一个模型的实例(方法delete())后抛出之前发挥作用。
  3. pre_init/post_init : 这个信号在实例化一个模型(__init__()方法)之前/之后抛出。

如何使用Signals ion Django

例如,如果我们想在使用post_save信号创建用户时立即创建一个用户的资料。

Models.py

from django.db import models
from django.contrib.auth.models import User
from PIL import Image
 
 
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    image = models.ImageField(default='default.jpg', upload_to='profile_pics')
 
    def __str__(self):
        return f'{self.user.username} Profile'

Views.py

from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
 
 
def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            messages.success(request, f'Your account has been created! You are now able to log in')
            return redirect('login')
    else:
        form = UserRegisterForm()
    return render(request, 'users/register.html', {'form': form})
 
 
@login_required
def profile(request):
    if request.method == 'POST':
        u_form = UserUpdateForm(request.POST, instance=request.user)
        p_form = ProfileUpdateForm(request.POST,
                                   request.FILES,
                                   instance=request.user.profile)
        if u_form.is_valid() and p_form.is_valid():
            u_form.save()
            p_form.save()
            messages.success(request, f'Your account has been updated!')
            return redirect('profile')
 
    else:
        u_form = UserUpdateForm(instance=request.user)
        p_form = ProfileUpdateForm(instance=request.user.profile)
 
    context = {
        'u_form': u_form,
        'p_form': p_form
    }
 
    return render(request, 'users/profile.html', context)

Forms.py

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
 
 
class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()
 
    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']
 
 
class UserUpdateForm(forms.ModelForm):
    email = forms.EmailField()
 
    class Meta:
        model = User
        fields = ['username', 'email']
 
 
class ProfileUpdateForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['image']

Signals.py(使用接收器方法)

# code
from django.db.models.signals import post_save, pre_delete
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
 
 
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
  
@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
        instance.profile.save()

如果你是Django的新手,你可能会对这段代码感到困惑,那么正在发生的事情是,当用户模型被保存时,一个名为create_profile的信号被触发,它创建了一个Profile实例,其外键指向了用户的实例。另一个方法save_profile只是保存了这个实例。

现在我们来了解一下这些论点

  • receiver – 接收信号并做某事的功能。
  • sender – 发出信号
  • created – 检查模型是否被创建。
  • instance – 创建的模型实例
  • kwargs -通配符关键字参数

另一种连接信号与功能的方式。

你需要将信号文件与app.py文件的准备功能连接起来,以便使用它们。

from django.apps import AppConfig
 
class UsersConfig(AppConfig):
    name = 'users'
 
    def ready(self):
        import users.signals

这里的信号是活的。

如果我们创建一个用户

如何在Django中创建和使用信号?

那么他的资料就会自动创建。

如何在Django中创建和使用信号?

你也可以在管理视图中检查它

如何在Django中创建和使用信号?

使用接收者方法的pre_save –

Pre_save方法是在调用save函数之前被激发的,而且只有在成功执行pre_save方法之后,模型才被保存。

# code
from django.db.models.signals import post_save, pre_delete,pre_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
 
 
@receiver(pre_save, sender=User)
def checker(sender, instance, **kwargs):
    if instance.id is None:
        pass
    else:
      current=instance
      previous=User.objects.get(id=instance.id)
      if previous.reaction!= current.reaction:
               #save method can be called

如果反应发生变化,我们就使用这个。

使用信号连接法

上述方法的替代方法是使用连接方法发射信号。

如果你只是使用post_save.connect(my_function),那么只要任何保存方法被触发,它就会被触发。

post_save.connect(my_function_post_save, sender=MyModel)
pre_save.connect(my_function, sender= UserTextMessage)

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

Django 教程