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

Django Field Lookups的lte查询异常,求排查解决

问题排查与修复方案

核心问题:字符串与数值的比较逻辑错误

你的Game_Info.game_rank和User_Info.rank均使用CharField存储等级数值,这会导致数据库执行game_rank__lte条件时,按字符串字典序而非数值大小进行比较。例如字符串"99"会被判定为大于"500"(因为第一个字符'9'的ASCII码大于'5'),最终导致rank为500的用户无法解锁game_rank为"99"的游戏,出现逻辑异常。

修复步骤

1. 修正模型字段类型

将两个存储等级的字段从CharField改为IntegerField,确保数值比较逻辑正确:

models.py

class Game_Info(models.Model):
    id = models.IntegerField(primary_key=True, unique=True, blank=True, editable=False)
    game_title = models.CharField(max_length=100, null=True)
    # 替换为IntegerField,补充默认值与空值处理
    game_rank = models.IntegerField(null=True, blank=True, default=0)
    game_image = models.ImageField(default='default.png', upload_to='game_covers', null=True, blank=True)
    featured_game = models.BooleanField(default=False)  # 用False替代0,语义更清晰

class User_Info(models.Model):
    id = models.IntegerField(primary_key=True, blank=True)
    image = models.ImageField(default='/profile_pics/default.png', upload_to='profile_pics', null=True, blank=True)
    user = models.OneToOneField(settings.AUTH_USER_MODEL,blank=True, null=True, on_delete=models.CASCADE)
    # 替换为IntegerField,保留默认值1
    rank = models.IntegerField(null=True, blank=True, default=1)    
    user_games_enabled = models.ManyToManyField(Game_Info, blank=True)
    # 移除无效的limit_choices_to:Game_Info中不存在unlocked_game字段

修改后执行数据库迁移:

python manage.py makemigrations
python manage.py migrate

2. 优化视图逻辑(可选)

简化冗余代码,同时处理rank为空的边界情况:

views.py

from django.db.models import Case, When, Value, BooleanField

def account_view_home(request):
    # 初始化默认值,避免重复代码
    user_profile = User_Info.objects.none()
    user_profile_games = Game_Info.objects.all()

    if request.user.is_authenticated:
        # 用get_or_create避免用户无对应User_Info记录的情况
        user_profile_game_obj, created = User_Info.objects.get_or_create(user=request.user)
        user_profile_rank = user_profile_game_obj.rank or 0  # 处理rank为null的场景
        user_profile = User_Info.objects.filter(user=request.user)

        user_profile_games = Game_Info.objects.annotate(
            user_unlocked_game=Case(
                When(game_rank__lte=user_profile_rank, then=Value(True)),
                default=Value(False),
                output_field=BooleanField()
            )
        )

    context = {
        'user_profile': user_profile,
        'user_profile_games': user_profile_games
    }
    return render(request, 'home.html', context)

3. 模板层简化优化

Boolean字段可直接判断,无需与True比较:

home.html

{% for content in user_profile_games %}
{% if content.featured_game %}
    {% if content.user_unlocked_game %}
    <!-- 已解锁游戏逻辑 -->
    <a class="game-tile-container" href="{% url 'detail' content.pk %}">
        <div class="image-wrapper" style="padding-right: 5px;">
            <span class="material-icons play_btn">play_circle_filled</span>
            <img class="game-art" src="{{content.game_image.url }}" />
        </div>
    </a>
    <p class="game-title">{{ content.game_title }}</p>
    {% else %}
    <!-- 锁定游戏逻辑 -->
    <a class="game-tile-container" href="{% url 'detail' content.pk %}">
        <div class="locked_game" style="padding-right: 5px;">
            <div class="image-wrapper">
                <img class="game-art" src="{{content.game_image.url }}" />
                <img class="lock-img" src="{% static 'images/treasure-chest-closed-alt.png' %}" />
                <button class="level-up">Reach level {{ content.game_rank }} to unlock</button>
            </div>
        </div>
    </a>
    <p class="game-title">{{ content.game_title }}</p>
    {% endif %}
{% endif %}
{% endfor %}

额外注意事项

  • 若已有字符串类型的等级数据,迁移时Django会自动尝试转为整数,若存在非数值内容会导致迁移失败,需提前清理无效数据。
  • 原User_Info.user_games_enabled中的limit_choices_to参数无效,已移除,若需限制可选游戏,需补充对应字段并维护其值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 01:09:54