我正在对我的应用程序中搜索功能的自动完成部分进行一些更新,由于某种原因,我收到了一个针对注销用户的错误,显示为TypeError: Field 'id' expected a number but got <SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x1088a5e20>>.

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

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

我正在构建一个游戏应用程序,用户可以根据他们在我们应用程序中的排名来玩某些游戏.因此,当用户登录时,我希望自动完成功能能够反映他们解锁的游戏. 假设用户的rank100,则会显示game_rankrank及以下的所有游戏. 对于注销的用户,我希望所有游戏都能显示出来.

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

以下是我的代码.

如有任何帮助,我们将非常感激!

全力以赴!

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.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({})

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

推荐答案

根据您所显示的查询,已注销的用户应该甚至不能导航到此视图.我会用@login_required英镑装饰一下风景.

您看到的问题就在这条线上:

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

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

或者,您可以使用user.is_authenticated()更改视图的行为


考虑到这些需求,我会将您的观点重构为以下几点.

from http import HTTPStatus


def search_results_view(request):
    if not request.headers.get("x-requested-with") == "XMLHttpRequest":
        # Give an error response when something unexpected happens
        return JsonResponse(
            {"error": "Invalid request"}, status_code=HTTPStatus.BAD_REQUEST
        )

    # Create the primary queryset, then additionally filter it if the user is logged in
    game = request.POST.get("game")
    games = Game_Info.objects.filter(game_title__icontains=game).order_by("game_title")
    if request.user.is_authenticated():
        user_info = User_Info.objects.get(user=request.user)
        games.filter(game_rank__lte=user_info.rank)

    # Return the JSON response with a list comprehension, limiting the queryset to 4 items
    return JsonResponse(
        {
            "data": [
                {
                    "pk": game.pk,
                    "name": game.game_title,
                    "game_provider": game.game_provider,
                    "image": game.game_image.url,
                    "url": reverse("detail", args=[game.pk]),
                }
                for game in games.limit(4)
            ]
        }
    )

这样,我将重构您的前端代码以处理接收空响应和错误响应.

我在这里还有更多的事情要做.

  • 您实际上并没有使用Django的模板系统,所以编写DRF application可能会更好.
  • 您的命名约定有一些问题.根据PEP8的指导方针,class names should be in UpperCamelCase,所以你的型号应该是GameInfoUserInfo.
  • 为此,我将使用ListView类,而不是方法视图,并将其定制为返回JsonResponse.不完全有必要,但为什么要做额外的工作,而ListView就是为这个目的而设计的

我可以继续下go ,可能会再增加3-4个东西,但我很固执己见,所以我不会这么做.

Python相关问答推荐

Python 3.12中的通用[T]类方法隐式类型检索

使用numpy提取数据块

Julia CSV for Python中的等效性Pandas index_col参数

如何在Python脚本中附加一个Google tab(已经打开)

为什么np. exp(1000)给出溢出警告,而np. exp(—100000)没有给出下溢警告?

在pandas数据框中计算相对体积比指标,并添加指标值作为新列

numpy.unique如何消除重复列?

具有相同图例 colored颜色 和标签的堆叠子图

Gunicorn无法启动Flask应用,因为无法将应用解析为属性名或函数调用.'"'' "

Pandas—堆栈多索引头,但不包括第一列

语法错误:文档. evaluate:表达式不是合法表达式

Autocad使用pyautocad/comtypes将对象从一个图形复制到另一个图形

504未连接IB API TWS错误—即使API连接显示已接受''

Pandas数据框上的滚动平均值,其中平均值的中心基于另一数据框的时间

如果不使用. to_list()[0],我如何从一个pandas DataFrame中获取一个值?

Polars时间戳同步延迟计算

我怎样才能让深度测试在OpenGL中使用Python和PyGame呢?

用LAKEF划分实木地板AWS Wrangler

删除另一个div中的特定div容器

使用Django标签显示信息