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

Django游戏应用:如何按登录用户等级展示解锁游戏?

问题描述

我正在开发一款游戏应用,已登录用户可根据其在应用中的等级(rank)访问不同游戏。例如,若登录用户的等级为100,则展示等级(game_rank)≤100的所有游戏,其余游戏将处于锁定状态。

目前我的HTML仅能显示通用的锁定/解锁游戏状态,无法实现用户针对性展示。现咨询实现该功能的最优方案:如何基于登录用户的等级展示可解锁的游戏?

相关字段说明

  • 游戏等级为Game_Info模型的game_rank字段
  • 登录用户的等级为User_Info模型的rank字段

现有代码

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)
    game_rank = models.CharField(max_length=1000, null=True, blank=True)
    game_image = models.ImageField(default='default.png', upload_to='game_covers', null=True, blank=True)
    locked_game = models.BooleanField(default=0)
    unlocked_game = models.BooleanField(default=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)
    rank = models.CharField(max_length=100, null=True, blank=True, default=1)    
    user_games_enabled = models.ManyToManyField(Game_Info, blank=True, limit_choices_to={'unlocked_game': True})

home.html

{% for content in user_profile_games %}
{% if content.locked_game == True %}

<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>

{% else %}
{% endif %}
{% endif %}

{% if content.unlocked_game == True %}

<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>

{% endif %}
{% endif %}

{% endfor %}

views.py

def account_view_home(request):
    user_profile = User_Info.objects.all()
    user_profile_games = Game_Info.objects.all()
    user = request.user

    
    if request.user.is_authenticated:
        user_profile = User_Info.objects.filter(user=request.user)
        context = {
            'user_profile': user_profile,
            'user_profile_games' : user_profile_games
        }

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

解决方案

1. 修正字段类型(核心问题)

当前rank和game_rank用了CharField,无法直接做数值大小比较,必须改成IntegerField。另外locked_game和unlocked_game这两个固定布尔字段完全没必要——游戏是否解锁是动态基于用户等级判断的,不需要存在数据库中。修改后的模型:

# 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,支持数值比较,默认等级1
    game_rank = models.IntegerField(null=True, blank=True, default=1)
    game_image = models.ImageField(default='default.png', upload_to='game_covers', null=True, blank=True)
    # 移除固定锁定/解锁字段
    # locked_game = models.BooleanField(default=0)
    # unlocked_game = models.BooleanField(default=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)

修改后执行数据库迁移:

python manage.py makemigrations
python manage.py migrate

2. 优化视图逻辑

获取当前登录用户的等级并传递给模板,用get_or_create避免用户未创建User_Info实例的情况:

# views.py
def account_view_home(request):
    user_profile_games = Game_Info.objects.all()
    user_rank = 0  # 未登录用户默认等级设为0,可按需调整
    user_profile = None

    if request.user.is_authenticated:
        # 获取或创建当前用户的User_Info实例
        user_profile, created = User_Info.objects.get_or_create(user=request.user)
        user_rank = user_profile.rank or 1  # 处理rank为None的情况

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

3. 重构模板判断逻辑

直接用user_rank和游戏的game_rank做数值比较,动态显示锁定/解锁状态:

<!-- home.html -->
{% for content in user_profile_games %}
    {% if user_rank >= content.game_rank %}
        <!-- 解锁状态:展示可玩游戏卡片 -->
        <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 %}
{% endfor %}

可选:支持手动解锁游戏

若需要给用户手动解锁游戏(如付费、活动奖励),保留user_games_enabled字段后,修改模板判断条件:

{% for content in user_profile_games %}
    {% if user_rank >= content.game_rank or (user_profile and content in user_profile.user_games_enabled.all) %}
        <!-- 解锁状态 -->
        ...
    {% else %}
        <!-- 锁定状态 -->
        ...
    {% endif %}
{% endfor %}

内容的提问来源于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 12:57:03