[英]'<' not supported between instances of 'method' and 'method' - Python, Django
I'm trying to do Winerama Recommender Tutorial . 我正在尝试做Winerama推荐教程 。 I met a error which I can't solve. 我遇到了我无法解决的错误。 When I try to go to the tab 'recommendation list' the browser returned the following error. 当我尝试转到“推荐列表”标签时,浏览器返回以下错误。
Error 错误
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/recommendation/
Django Version: 2.0.7
Python Version: 3.7.0
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bootstrap3',
'reviews',
'registration']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "C:\Users\tymot\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\exception.py" in inner
35. response = get_response(request)
File "C:\Users\tymot\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\base.py" in _get_response
128. response = self.process_exception_by_middleware(e, request)
File "C:\Users\tymot\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\core\handlers\base.py" in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\tymot\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
21. return view_func(request, *args, **kwargs)
File "C:\Users\tymot\Desktop\Cd-12.50-20.08\env\my_app\winerama\reviews\views.py" in user_recommendation_list
89. reverse=True
Exception Type: TypeError at /recommendation/
Exception Value: '<' not supported between instances of 'method' and 'method'
I created everything according to the steps in the tutorial. 我根据教程中的步骤创建了所有内容。
File models.py 文件models.py
from django.db import models
from django.contrib.auth.models import User
import numpy as np
class Wine(models.Model):
name = models.CharField(max_length=200)
def average_rating(self):
all_ratings = [list(map(lambda x: x.rating, self.review_set.all()))]
return np.mean(all_ratings)
def __unicode__(self):
return self.name
class Review(models.Model):
RATING_CHOICES = (
(1, '1'),
(2, '2'),
(3, '3'),
(4, '4'),
(5, '5'),
)
wine = models.ForeignKey(Wine, on_delete=models.CASCADE)
pub_date = models.DateTimeField('date published')
user_name = models.CharField(max_length=100)
comment = models.CharField(max_length=200)
rating = models.IntegerField(choices=RATING_CHOICES)
class Cluster(models.Model):
name = models.CharField(max_length=100)
users = models.ManyToManyField(User)
def get_members(self):
return "\n".join([u.username for u in self.users.all()])
Next i added admin.py and create 3 klaster with users in '/admin'. 接下来,我添加了admin.py并在“ / admin”中与用户一起创建了3个klaster。
from django.contrib import admin
from .models import Wine, Review, Cluster
class ReviewAdmin(admin.ModelAdmin):
model = Review
list_display = ('wine', 'rating', 'user_name', 'comment', 'pub_date')
list_filter = ['pub_date', 'user_name']
search_fields = ['comment']
class ClusterAdmin(admin.ModelAdmin):
model = Cluster
list_display = ['name', 'get_members']
admin.site.register(Wine)
admin.site.register(Review, ReviewAdmin)
admin.site.register(Cluster, ClusterAdmin)
My file views.py 我的文件views.py
@login_required
def user_recommendation_list(request):
# get request user reviewed wines
user_reviews = Review.objects.filter(user_name=request.user.username).prefetch_related('wine')
user_reviews_wine_ids = set(map(lambda x: x.wine.id, user_reviews))
# get request user cluster name (just the first one righ now)
user_cluster_name = \
User.objects.get(username=request.user.username).cluster_set.first().name
# get usernames for other memebers of the cluster
user_cluster_other_members = \
Cluster.objects.get(name=user_cluster_name).users \
.exclude(username=request.user.username).all()
other_members_usernames = set(map(lambda x: x.username, user_cluster_other_members))
# get reviews by those users, excluding wines reviewed by the request user
other_users_reviews = \
Review.objects.filter(user_name__in=other_members_usernames) \
.exclude(wine__id__in=user_reviews_wine_ids)
other_users_reviews_wine_ids = set(map(lambda x: x.wine.id, other_users_reviews))
# then get a wine list including the previous IDs, order by rating
wine_list = sorted(
list(Wine.objects.filter(id__in=other_users_reviews_wine_ids)),
key=lambda x: x.average_rating,
reverse=True
)
return render(
request,
'reviews/user_recommendation_list.html',
{'username': request.user.username, 'wine_list': wine_list}
)
I will mark that when I try use simple version everything works fine. 我将标记为当我尝试使用简单版本时,一切正常。
@login_required
def user_recommendation_list(request):
# get this user reviews
user_reviews = Review.objects.filter(user_name=request.user.username).prefetch_related('wine')
# from the reviews, get a set of wine IDs
user_reviews_wine_ids = set(map(lambda x: x.wine.id, user_reviews))
# then get a wine list excluding the previous IDs
wine_list = Wine.objects.exclude(id__in=user_reviews_wine_ids)
return render(
request,
'reviews/user_recommendation_list.html',
{'username': request.user.username,'wine_list': wine_list}
)
My error is at this stage (2.5) of the tutorial. 我的错误是在本教程的这一阶段(2.5) 。 Stage 2.4 works good. 2.4阶段效果很好。 Everything indicates that something is wrong in views.py. 一切都表明views.py中有问题。
Any help will be very appreciated. 任何帮助将不胜感激。
There is a difference between a method and the value a method returns. 方法和方法返回的值之间存在差异。 Here in your Wine
model, we see: 在您的Wine
模型中,我们看到:
from django.db.models import Avg
class Wine(models.Model):
name = models.CharField(max_length=200)
def average_rating(self):
return self.review_set.aggregate(
mean=Avg('rating')
)['mean']
def __unicode__(self):
return self.name
(I rewrote it to make an efficienty query, instead of Python/Django/Numpy let do the work). (我重写了它以进行高效查询,而不是让Python / Django / Numpy来完成工作)。
If you now have a Wine
object named some_wine
, then you do not get the average rating here with some_wine.average_rating
, since this will return a method, but by calling the function, so some_wine.average_rating ()
. 如果您现在有一个名为some_wine
的Wine
对象,那么您在这里不会获得some_wine.average_rating
的平均评分,因为这将返回一个方法,而是通过调用函数some_wine.average_rating ()
。
There are some options here: 这里有一些选项:
calling the function in the lambda expression : 在lambda表达式中调用函数:
wine_list = sorted( list(Wine.objects.filter(id__in=other_users_reviews_wine_ids)), key=lambda x: x.average_rating () , reverse=True )
define the method as a property, in that case, you no longer call the function, it is the called behind the curtains, so: 将方法定义为属性,在这种情况下,您不再调用函数,而是在幕后进行调用,因此:
from django.db.models import Avg class Wine(models.Model): name = models.CharField(max_length=200) @property def average_rating(self): return self.review_set.aggregate( mean= Avg('rating') )['mean'] def __unicode__(self): return self.name
use Wine.average_rating
as key, since then it is a function that is called with instances: 使用Wine.average_rating
作为键,因为这是一个实例调用的函数:
wine_list = sorted( list(Wine.objects.filter(id__in=other_users_reviews_wine_ids)), key= Wine.average_rating , reverse=True )
order the Wine
objects already by the database, by using .annotate(..)
: 订购 Wine
的数据库对象已经通过使用.annotate(..)
wine_list = Wine.objects.filter( id__in=other_users_reviews_wine_ids ).annotate( mean=Avg('rating') ).order_by('-rating')
The latest approach is probably the most efficient, since a database typically is optimized for such queries, furthermore this will get done by a single query. 最新的方法可能是最有效的,因为数据库通常针对此类查询进行了优化,此外,这将通过单个查询来完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.