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

Django自定义Token登录系统报错排查及用户目的地过滤求助

问题排查与解决方案

错误原因分析

  • NOT NULL约束失败:Session模型中user是OneToOneField(非空约束),但登录视图里先创建Session对象却未关联用户,直接触发数据库非空校验错误;且Session创建逻辑放在用户验证之前,无论用户是否合法都会生成无效Session。
  • 密码验证逻辑错误:User模型的check_password方法逻辑颠倒——将数据库中已存储的哈希密码再次哈希,再与传入的哈希密码对比,永远无法匹配。

代码修复方案

1. 修复User模型的密码验证方法

from django.db import models
import hashlib

class User(models.Model):
    id = models.BigAutoField(primary_key=True)
    name = models.TextField()
    email = models.EmailField(unique=True)
    password_hash = models.TextField()

    def check_password(self, raw_password):
        # 对用户输入的原始密码哈希后,与数据库存储值对比
        hasher = hashlib.sha256()
        hasher.update(bytes(raw_password, "UTF-8"))
        input_hash = hasher.hexdigest()
        return self.password_hash == input_hash

class Session(models.Model):
    id = models.BigAutoField(primary_key=True)
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    token = models.TextField()

class Destination(models.Model):
    id = models.BigAutoField(primary_key=True)
    name = models.TextField()
    review = models.TextField()
    rating = models.PositiveIntegerField()
    share_publicly = models.BooleanField(default=False)
    user = models.ForeignKey("User", related_name="destinations", on_delete=models.CASCADE)

2. 修复登录视图逻辑

调整执行顺序:先验证用户身份,再创建关联用户的Session,最后设置Cookie

import hashlib
import random
import string
from django.http import HttpRequest, HttpResponse, Http404, redirect
from django.shortcuts import render
from .models import User, Session

def login(request: HttpRequest):
    if request.method == "POST":
        email = request.POST.get('email')
        raw_password = request.POST.get('password')

        try: 
            user = User.objects.get(email=email)
            # 使用修复后的密码验证方法
            if user.check_password(raw_password):
                # 生成32位随机token
                token = ''.join(random.choice(string.ascii_lowercase) for _ in range(32))
                # 创建关联当前用户的Session
                Session.objects.create(user=user, token=token)
                # 重定向首页并设置Cookie
                response = redirect("/")
                response.set_cookie('token', token)
                return response
            else:
                return HttpResponse("Invalid password")
        except User.DoesNotExist:
            return Http404("Invalid email")
    
    return render(request, "destination/login.html")

仅显示当前登录用户的目的地

1. 编写获取当前登录用户的工具函数

# 可放在app的utils.py文件中
from .models import Session

def get_current_user(request):
    token = request.COOKIES.get('token')
    if not token:
        return None
    try:
        session = Session.objects.get(token=token)
        return session.user
    except Session.DoesNotExist:
        return None

2. 在视图中过滤用户专属目的地

from django.shortcuts import render
from .models import Destination
from .utils import get_current_user

def user_destinations(request):
    current_user = get_current_user(request)
    if not current_user:
        return redirect("/login")
    
    # 方法1:直接通过外键过滤
    destinations = Destination.objects.filter(user=current_user)
    # 方法2:使用related_name反向查询(更简洁)
    # destinations = current_user.destinations.all()
    
    return render(request, "destination/user_destinations.html", {"destinations": destinations})

内容的提问来源于stack exchange,提问作者Wade Kemmsies

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 23:41:13