如何在 Django 中创建和使用信号?
信号用于对模型实例的修改执行任何操作。信号是帮助我们将事件与动作联系起来的实用程序。我们可以开发一个在信号调用时运行的函数。换句话说,信号用于对数据库中特定条目的修改/创建执行某些操作。例如,一旦在数据库中创建了一个新的用户实例,就希望创建一个配置文件实例
有 3 种类型的信号。
- pre_save/post_save :此信号在方法 save() 之前/之后起作用。
- pre_delete/post_delete :这个信号在删除模型的实例(方法 delete())之后这个信号被抛出之前起作用。
- pre_init/post_init :在实例化模型之前/之后抛出此信号(__init__() 方法)。
Refer to the following articles to check how to create a project and an app in Django.
How to Create a Basic Project using MVT in Django?
How to Create an App in Django ?
如何使用信号离子 Django?
例如,如果我们想在使用 post_save 信号创建用户后立即创建用户的个人资料
模型.py
Python3
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'
Python3
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)
Python3
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']
Python3
# 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()
Python3
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals
Python3
# 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
视图.py
蟒蛇3
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)
表单.py
蟒蛇3
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(使用接收器方法)
蟒蛇3
# 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 的新手,您可能会对这段代码感到困惑,因此,当保存 User 模型时,会触发一个名为create_profile的信号,该信号创建一个 Profile 实例,外键指向用户的实例.另一种方法save_profile只是保存实例。
现在让我们了解这些论点
- 接收器-谁接收信号,并且做了该函数。
- sender – 发送信号
- created — 检查模型是否已创建
- instance — 创建的模型实例
- **kwargs –通配符关键字参数
将信号与函数连接的另一种方法:
您需要将信号文件与 app.py 文件就绪函数连接起来才能使用它们。
蟒蛇3
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals
信号在这里。
如果我们创建一个用户
然后他的个人资料会自动创建。
您也可以在管理员视图中查看
pre_save 使用接收器方法 –
Pre_save 方法在调用 save函数之前触发,并且模型也只有在 pre_save 方法成功执行后才会保存
蟒蛇3
# 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),那么只要任何 save 方法被触发,它就会被触发。
post_save.connect(my_function_post_save, sender=MyModel)
pre_save.connect(my_function, sender= UserTextMessage)