You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 12:35:39