Django - 自动完成搜索会对注销用户引发错误?

问题描述 投票:0回答:1

我正在对我的应用程序中搜索功能的自动完成部分进行一些更新,由于某种原因,我收到注销用户的错误消息,内容为

TypeError: Field 'id' expected a number but got <SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x1088a5e20>>.

这只发生在注销用户身上。当用户登录时,自动完成功能会按照构建的方式工作,所以我知道我错过了一些东西,但我只是不知道是什么。

需要更改哪些内容才能解决此问题?

我正在构建一个游戏应用程序,用户可以根据他们在我们应用程序中的排名来玩某些游戏。因此,当用户登录时,我希望自动完成功能能够反映他们已解锁的游戏。 假设用户的

rank
100
,那么所有
game_rank
为 100 及以下的游戏都会显示。 对于注销的用户,我希望显示所有游戏。

在我的

views.py
代码中根据我测试的内容做了一些注释,并将 JavaScript 添加到搜索功能中,以防万一。

下面的屏幕截图显示了用户注销和登录时显示的内容。

注销屏幕截图

登录截图

下面是我的代码。

非常感谢任何帮助!

尽我所能!

模型.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.IntegerField(default=1)
    game_image = models.ImageField(default='default.png', upload_to='game_covers', null=True, blank=True)


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.IntegerField(default=1)   

views.py

def search_results_view(request):
    if request.headers.get('x-requested-with') == 'XMLHttpRequest': 
        res = None
        game = request.POST.get('game')
        print(game)

        ## This works for both logged in and logged out users but inlcudes all games. Would like to have this for logged out users. Commenting this out to test below. 
        # qs = Game_Info.objects.filter(game_title__icontains=game).order_by('game_title')[:4]

        ## This only works for when users are logged in. 
        user_profile_game_obj = User_Info.objects.get(user=request.user)
        user_profile_rank = int(user_profile_game_obj.rank)
        qs = Game_Info.objects.filter(game_title__icontains=game, game_rank__lte=user_profile_rank).order_by('game_title')[:4]

        if len(qs) > 0 and len(game) > 0:
            data = []
            for pos in qs:
                item ={
                    'pk': pos.pk,
                    'name': pos.game_title,
                    'game_provider': pos.game_provider,
                    'image': str(pos.game_image.url),
                    'url': reverse('detail', args=[pos.pk]),
                }
                data.append(item)
            res = data
        else:
            res = 'No games found...'

        return JsonResponse({'data': res})
    return JsonResponse({})

自定义.js

// Live Search Functionalty 
$(function () {
    const url = window.location.href
    const searchForm = document.getElementById("search-form");
    const searchInput = document.getElementById("search_input_field");
    const resultsBox = document.getElementById("search-results");
    const csrf = document.getElementsByName('csrfmiddlewaretoken')[0].value

    const sendSearchData = (game) =>{
        $.ajax ({
            type: 'POST',
            url: '/games/',

            data: {
                'csrfmiddlewaretoken': csrf,
                'game' : game,
            },
            success: (res)=> {
                console.log(res.data)
                const data = res.data
                if (Array.isArray(data)) {
                    resultsBox.innerHTML = `<div class="search_heading"><h1>Recommended Games</h1></div>`
                    data.forEach(game=> {
                        resultsBox.innerHTML += `                    
                            <a href="${game.url}" class="item" >                          
                                <div class="row">
                                    <div class="search-cover-container">
                                        <img src="${game.image}" class="game-img">
                                    </div>
                                    <div class="search-title-container">
                                        <p>${game.name}</p>
                                        <span class="publisher_title">${game.game_provider}</span>
                                    </div>
                                    <div class="search-icon-container">
                                        <i class="material-icons">trending_up</i>
                                    </div>
                                </div>
                            </a>
                        `
                    })
                } else {
                   if (searchInput.value.length > 0) {
                    resultsBox.innerHTML = `<h2>${data}</h2>`
                   } else {
                    resultsBox.classList.add('not_visible')
                   }
                }
            },
            error: (err)=> {
                console.log(err)
            }
        })
    }

    searchInput.addEventListener('keyup', e=> {
        sendSearchData(e.target.value)
    })

});

base.html

            <form method="POST" autocomplete="off" id="search-form" action="{% url 'search_results' %}">
                {% csrf_token %}
                <div class="input-group">
                    <input id="search_input_field" type="text" name="q" autocomplete="off" class="form-control gs-search-bar" placeholder="Search Games..." value="">
                    <div id="search-results" class="results-container not_visible"></div>
                    <span class="search-clear">x</span>
                    <button id="search-btn" type="submit" class="btn btn-primary search-button" disabled>
                        <span class="input-group-addon">
                            <i class="zmdi zmdi-search"></i>
                        </span> 
                    </button>
                </div>
            </form>
python django django-models django-views django-templates
1个回答
0
投票

根据您显示的查询,注销的用户甚至应该无法导航到此视图。我会用

@login_required
来装饰视图。

您看到的问题就在这一行:

user_profile_game_obj = User_Info.objects.get(user=request.user)

当用户未登录时,

request.user
是一个
AnonymousUser
实例,没有ID。当进行该查询时,底层框架会获取所传递实例的 ID,在本例中该 ID 是不可解析的。您无法将
AnonymousUser
与记录关联,它们没有标识符,并且不能在查询中使用。

或者,您可以使用

user.is_authenticated()

更改视图的行为
© www.soinside.com 2019 - 2024. All rights reserved.