【发布时间】:2015-02-16 01:23:38
【问题描述】:
我正在构建一个应用来按类别向用户显示随机问题。 每个用户都应该通过“是”、“否”或“否”对问题进行投票。 该应用程序计算每个问题的投票数,每个用户每个问题可以投票一次。
问题应随机出现在用户面前,每个用户出现的次数不得超过一次(用户必须投票才能继续)。
models.py:
class Category(models.Model):
name = models.CharField(max_length=500, null=False)
parent = models.ForeignKey("self", null=True, default=None)
class Question(models.Model):
question = models.CharField(max_length=500, null=False, blank=False)
title = models.CharField(max_length=100, null=False, blank=False)
category = models.ForeignKey(Category, null=True, default=None, blank=True)
no_count = models.BigIntegerField(default=0)
yes_count = models.BigIntegerField(default=0)
na_count = models.BigIntegerField(default=0)
user = models.ForeignKey(User, null=True, default=None)
rand = models.FloatField(null=True, default=0)
def save(self, *args, **kwargs):
self.rand = random.random()
super(Picture, self).save(*args, **kwargs)
class Vote(models.Model):
VOTE_CHOICES = (
(1, 'Yes'),
(2, 'No'),
(3, 'N/A'),
)
user = models.ForeignKey(User)
question = models.ForeignKey(Question, null=True, default=None)
user_vote = models.IntegerField(choices=VOTE_CHOICES)
class UserSettings(models.Model):
user = models.OneToOneField(User)
categories = models.CommaSeparatedIntegerField(max_length=1000, null=True)
views.py:
class GetQuestions(generics.ListAPIView):
model = Question
serializer_class = QuestionSerializer
def get_queryset(self):
user = self.request.user
lookup = dict()
categories = user.usersettings.categories
if categories is None:
categories = Category.objects.filter(~Q(parent=None)).values_list('id', flat=True)
else:
categories = ast.literal_eval(categories)
lookup['category__in'] = categories
voted = Vote.objects.filter(user=self.request.user).values_list('question')
questions = Question.objects.filter(**lookup).exclude(id__in=voted).order_by('rand')
return questions
class NewVote(generics.CreateAPIView):
model = Vote
serializer_class = VoteSerializer
def post(self, request, *args, **kwargs):
current_vote = Vote.objects.filter(user=request.user, picture=int(self.request.DATA['question']))
if current_vote:
return HttpResponseForbidden()
return super(NewVote, self).post(request, *args, **kwargs)
def pre_save(self, obj):
obj.user = self.request.user
def post_save(self, obj, created=False):
if created:
vote_count = obj.vote.get_user_vote_display().lower().replace(" ", "")
vote_count += "_count"
count = getattr(obj.picture, vote_count)
setattr(obj.picture, vote_count, count + 1)
obj.picture.save()
在投票时,我只是增加问题的相关计数。 我的问题是:
- 选择随机问题的最佳方法是什么?目前我已经在问题上添加了随机字段并使用 order_by('rand') - 有没有更好的方法?
- 用户选择问题类别的最佳方式是什么?目前我正在使用过滤器 category__in
- 最重要的一项 - 如何排除用户已经投票的问题?目前我只是从投票表中选择 user = request.user 并使用“NOT IN”的所有问题 - 缩放时这肯定不好......
欢迎提供概念、代码示例、链接。
非常感谢
【问题讨论】:
-
同一个问题能出现在更多用户面前吗?
-
是的,同样的问题可以(并且应该)出现在不同的用户面前。
-
如果你的设计中
Vote有ManyToManyField和User和through='Question',那不是更好吗? -
您的意思是不要让用户作为投票的外键,而是通过问题使其多对多,而不是删除问题字段?我当然可以这样做,但我能从中得到什么?我还是会遇到同样的问题,不是吗?
-
你说q用户可以有更多问题,同一个问题可以出现给更多用户,那么这不就是ManyToMany的情况吗?我之前指定的设计在我看来似乎更自然
标签: python mysql django django-rest-framework