如何在Django不同视图间传递PIN值并完成激活注册流程
Django票务系统PIN值传递与状态更新问题
我正在开发一个Django票务系统,流程为PIN激活→访客注册:访客需先激活票务PIN,再完成活动注册,注册后可登录并更新个人资料。目前遇到核心问题:无法将PIN值从PIN激活视图正确传递到注册视图。
我尝试用request.session['pin'] = pin_value在激活视图存储PIN,在注册视图用user_pin = request.session.get('pin')获取。当前Guest.objects.create(guest_name=new_user, pin=user_pin)能正常读取会话变量,但Pin.objects.filter(value=user_pin).update(status='Activated')却无法生效——用字面量值测试该更新查询正常,但会话变量无法触发更新,导致注册流程卡壳。
模型代码
class Guest(models.Model): guest_name = models.OneToOneField(User, on_delete=models.CASCADE, blank=True) pin = models.CharField(max_length=6, default='No Pin', blank=True) def __str__(self): return f"{self.guest_name}" class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, null = True) surname = models.CharField(max_length=20, null=True) othernames = models.CharField(max_length=40, null=True) gender = models.CharField(max_length=6, choices=GENDER, blank=True, null=True) phone = PhoneNumberField() image = models.ImageField(default='avatar.jpg', blank=False, null=False, upload_to ='profile_images') def __str__(self): return f'{self.user.username}-Profile' class Pin(models.Model): ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) value = models.CharField(max_length=6, default=generate_pin, blank=True) added = models.DateTimeField(auto_now_add=True, blank=False) reference = models.UUIDField(primary_key = True, editable = False, default=uuid.uuid4) status = models.CharField(max_length=30, default='Not Activated') #Save Reference Number def save(self, *args, **kwargs): self.reference == str(uuid.uuid4()) super().save(*args, **kwargs) def __unicode__(self): return self.ticket class Meta: unique_together = ["ticket", "value"] def __str__(self): return f"{self.ticket}" def get_absolute_url(self): return reverse("pin-detail", args=[str(self.id)])
视图代码
def pin_activation(request): if request.method == "POST": #Create PIN form form = PinActivationForm(request.POST) #Get User Pin Value from Form pin_value = form['pin'].value() #Check if the the form has valid data in it if form.is_valid(): try: #Get user Pin with the one in the Database check_pin_status = Pin.objects.get(value=pin_value) except Pin.DoesNotExist: messages.error(request, f'{pin_value} Does Not Exist') return redirect('pin-activation') else: #Check PIN status if check_pin_status: #Get Event Ticket Date of the PIN event_date = check_pin_status.ticket.event.date #Get Current Date current_date = datetime.now().date() #Check if Event Date is Passed the Current Date if event_date < current_date: messages.error(request, 'Event Has Passed') return redirect('pin-activation') else: #Update the User Pin with a new status of Activated Pin.objects.filter(value=form['pin'].value()).update(status='Validated') #Message the User messages.success(request, 'Pin Validated Successfully') #Redirect the user to register for seat return redirect('register-guest') #Check filter the DB where the PIN status is Validated request.session['pin'] = pin_value elif Pin.objects.filter(value=form['pin'].value(), status="Validated"): messages.error(request, 'Pin Already Validated. Register for Seat') return redirect('register-guest') #Check Filter PIN in DB where Status is Activated elif Pin.objects.filter(value=form['pin'].value(), status="Activated"): messages.error(request, "Pin Already Activated, Login.") return redirect('user-login') else: messages.error(request, 'Something Went Wrong. Try again') else: form = PinActivationForm() context = { 'form':form, } return render(request, 'user/pin_activation.html', context) def register_guest(request): #get session variable user_pin = request.session.get('pin') form = GuestUserForm(request.POST) page_title = "Festival Registration" if request.method == 'POST': form = GuestUserForm(request.POST) pin_form = PinActivationForm(request.POST) if form.is_valid() and pin_form.is_valid(): new_user = form.save() Guest.objects.create(guest_name=new_user, pin=user_pin) Pin.objects.filter(value=user_pin).update(status='Activated') messages.success(request, 'Registered Successfully. Login') return redirect('user-login') else: form = GuestUserForm() pin_form = PinActivationForm() context = { 'form':form, 'pin_form':pin_form, 'page_title':page_title, } return render(request, 'user/register.html', context)
解决方案
1. 修复会话变量设置位置
原代码中request.session['pin'] = pin_value放在了if check_pin_status:分支的后面,但该分支内已经执行return redirect('register-guest'),导致会话变量从未被设置。需将会话变量设置移到return之前的有效分支中:
修改后的pin_activation视图:
def pin_activation(request): if request.method == "POST": form = PinActivationForm(request.POST) # 去除PIN值前后空格,避免查询匹配失败 pin_value = form['pin'].value().strip() if form.is_valid(): try: check_pin_status = Pin.objects.get(value=pin_value) except Pin.DoesNotExist: messages.error(request, f'{pin_value} Does Not Exist') return redirect('pin-activation') # 优先检查PIN状态 if check_pin_status.status == "Activated": messages.error(request, "Pin Already Activated, Login.") return redirect('user-login') elif check_pin_status.status == "Validated": messages.error(request, 'Pin Already Validated. Register for Seat') request.session['pin'] = pin_value return redirect('register-guest') # 检查活动是否已过期 event_date = check_pin_status.ticket.event.date current_date = datetime.now().date() if event_date < current_date: messages.error(request, 'Event Has Passed') return redirect('pin-activation') # 验证PIN并设置会话变量 Pin.objects.filter(value=pin_value).update(status='Validated') messages.success(request, 'Pin Validated Successfully') request.session['pin'] = pin_value return redirect('register-guest') else: messages.error(request, 'Something Went Wrong. Try again') else: form = PinActivationForm() return render(request, 'user/pin_activation.html', {'form':form})
2. 简化注册视图逻辑
注册视图无需再次验证PinActivationForm,且需先检查会话中是否存在PIN,防止用户直接访问注册页面:
修改后的register_guest视图:
def register_guest(request): user_pin = request.session.get('pin') # 会话中无PIN则强制跳转回激活页面 if not user_pin: messages.error(request, 'Please validate your PIN first') return redirect('pin-activation') page_title = "Festival Registration" if request.method == 'POST': form = GuestUserForm(request.POST) if form.is_valid(): new_user = form.save() # 创建Guest与User的关联 Guest.objects.create(guest_name=new_user, pin=user_pin) # 仅更新状态为Validated的PIN,避免重复激活 updated_count = Pin.objects.filter(value=user_pin, status='Validated').update(status='Activated') if updated_count == 0: messages.warning(request, 'PIN activation failed, please contact support') else: messages.success(request, 'Registered Successfully. Login') # 清除会话中的PIN,防止重复使用 del request.session['pin'] return redirect('user-login') else: form = GuestUserForm() context = { 'form':form, 'page_title':page_title, } return render(request, 'user/register.html', context)
3. 额外优化点
- 确保Django的会话配置正常(
settings.py中SESSION_ENGINE默认配置即可) - 可在
register_guest中添加PIN值的格式验证(如长度是否为6位),避免无效值写入数据库
内容的提问来源于stack exchange,提问作者apollos
相关产品推荐
相关产品推荐

