- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在通过构建一个简单的RPG来尝试使用Django。它有装甲升级。装甲有不同类别(例如头部和 body )。每个类别都有许多装甲。例如,“头部”类别可能包含“龙盔”,“鸭盔”,“针盔”等。
为了使用户看到该类别中可用的任何装甲,必须首先授予他们访问该类别中至少一个装甲的权限。届时,他们可以查看该类别中的所有盔甲,包括尚未购买的盔甲。
问题
我试图有效地查询数据库中某个类别的所有装甲,同时注意用户已被授予访问权限的那些装甲。我有某种工作方式,但不是全部。
相关代码
models.py
from django.contrib.auth.models import User
from django.db import models
class Armor(models.Model):
armor_category = models.ForeignKey('ArmorCategory')
name = models.CharField(max_length=100)
profile = models.ManyToManyField('Profile', through='ProfileArmor')
def __unicode__(self):
return self.name
class ArmorCategory(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(blank=True)
class Meta:
verbose_name_plural = 'Armor categories'
def __unicode__(self):
return self.name
class Profile(models.Model):
user = models.OneToOneField(User)
dob = models.DateField('Date of Birth')
def __unicode__(self):
return self.user.get_full_name()
class ProfileArmor(models.Model):
profile = models.ForeignKey(Profile)
armor = models.ForeignKey(Armor)
date_created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-date_created',)
def __unicode__(self):
return '%s: %s' % (self.profile.user.get_full_name(), self.armor.name)
from django.conf.urls import patterns, url
from core import views
urlpatterns = patterns('',
url(r'^upgrades/(?P<armor_category_slug>[-\w]+)/$', views.Upgrades.as_view(), name='upgrades'),
)
from django.db.models import Count, Q
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.views.generic.base import TemplateView
from .models import ArmorCategory
class Upgrades(TemplateView):
template_name = 'core/upgrades.html'
def get(self, request, *args, **kwargs):
# Make sure the slug is valid.
self.armor_category = get_object_or_404(ArmorCategory, slug=kwargs['armor_category_slug'])
# Make sure the user has been granted access to at least one item in
# this category, otherwise there is no point for the user to even be
# here.
if self.armor_category.armor_set.filter(
profilearmor__profile=self.request.user.profile
).count() == 0:
return HttpResponseRedirect('/')
return super(Upgrades, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
# THIS IS WHERE THE PROBLEM IS.
# Get all of the armor in this category, but also take note of which
# armor this user has been granted access to.
armor = self.armor_category.armor_set.filter(
Q(profilearmor__profile=self.request.user.profile) |
Q(profilearmor__profile=None)
).annotate(profile_armor_count=Count('profilearmor__id'))
print armor.query
for armor_item in armor:
print '%s: %s' % (armor_item.name, armor_item.profile_armor_count)
return {
'armor_category': self.armor_category,
'armor': armor,
}
for
循环中获得以下输出:
Dragon Helm: 0
Duck Helm: 1
Needle Helm: 0
Dragon Helm: 1
Needle Helm: 0
Duck Helm: 1
Needle Helm: 0
最佳答案
1.快速说明
当您在Django查询集中针对None
测试多对多关系时,请按以下步骤操作:
Q(profilearmor__profile=None)
self.armor_category.armor_set.filter(
Q(profilearmor__profile=self.request.user.profile) |
Q(profilearmor__profile=None))
self.request.user
可以访问或没有人可以访问的装甲项目。这就是为什么您对第二个用户的查询未能返回Duck Helm的行:因为某个人(即第一个用户)可以访问它。
SELECT `myapp_armor`.`id`, `myapp_armor`.`armor_category_id`, `myapp_armor`.`name`,
COUNT(`myapp_profilearmor`.`id`) AS `profile_armor_count`
FROM `myapp_armor`
LEFT OUTER JOIN `myapp_profilearmor`
ON `myapp_armor`.`id` = `myapp_profilearmor`.`armor_id`
AND `myapp_profilearmor`.`profile_id` = %s
WHERE `myapp_armor`.`armor_category_id` = %s
GROUP BY `myapp_armor`.`id`, `myapp_armor`.`armor_category_id`, `myapp_armor`.`name`
sql = '''
SELECT `myapp_armor`.`id`, `myapp_armor`.`armor_category_id`, `myapp_armor`.`name`,
COUNT(`myapp_profilearmor`.`id`) AS `profile_armor_count`
FROM `myapp_armor`
LEFT OUTER JOIN `myapp_profilearmor`
ON `myapp_armor`.`id` = `myapp_profilearmor`.`armor_id`
AND `myapp_profilearmor`.`profile_id` = %s
WHERE `myapp_armor`.`armor_category_id` = %s
GROUP BY `myapp_armor`.`id`, `myapp_armor`.`armor_category_id`, `myapp_armor`.`name`
'''
armor = Armor.objects.raw(sql, [self.request.user.profile.id, self.armor_category.id])
for armor_item in armor:
print('{:14}{}'.format(armor_item.name, armor_item.profile_armor_count))
>>> helmets = ArmorCategory.objects.get(id=1)
>>> profile = Profile.objects.get(id=1)
>>> armor = Armor.objects.raw(sql, [profile.id, helmets.id])
>>> for armor_item in armor:
... print('{:14}{}'.format(armor_item.name, armor_item.profile_armor_count))
...
Dragon Helm 0
Duck Helm 1
Needle Helm 0
armor = self.armor_category.armor_set.filter(
Q(profilearmor__profile=self.request.user.profile) |
Q(profilearmor__profile=None)
).annotate(profile_armor_count=Count('profilearmor__id'))
query
属性并将其转换为字符串来做到这一点:
>>> from django.db.models import Q
>>> helmets = ArmorCategory.objects.get(name='Helmets')
>>> profile = Profile.objects.get(id=1)
>>> print(helmets.armor_set.filter(Q(profilearmor__profile=profile) |
... Q(profilearmor__profile=None)
... ).annotate(profile_armor_count=Count('profilearmor__id')).query)
SELECT `myapp_armor`.`id`, `myapp_armor`.`armor_category_id`, `myapp_armor`.`name`,
COUNT(`myapp_profilearmor`.`id`) AS `profile_armor_count`
FROM `myapp_armor`
LEFT OUTER JOIN `myapp_profilearmor`
ON (`myapp_armor`.`id` = `myapp_profilearmor`.`armor_id`)
LEFT OUTER JOIN `myapp_profile`
ON (`myapp_profilearmor`.`profile_id` = `myapp_profile`.`id`)
WHERE (`myapp_armor`.`armor_category_id` = 1
AND (`myapp_profilearmor`.`profile_id` = 1
OR `myapp_profile`.`id` IS NULL))
GROUP BY `myapp_armor`.`id`, `myapp_armor`.`armor_category_id`, `myapp_armor`.`name`
ORDER BY NULL
mysql> SELECT * FROM myapp_armorcategory;
+----+---------+---------+
| id | name | slug |
+----+---------+---------+
| 1 | Helmets | helmets |
| 2 | Suits | suits |
+----+---------+---------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM myapp_armor;
+----+-------------------+-------------+
| id | armor_category_id | name |
+----+-------------------+-------------+
| 1 | 1 | Dragon Helm |
| 2 | 1 | Duck Helm |
| 3 | 1 | Needle Helm |
| 4 | 2 | Spiky Suit |
| 5 | 2 | Flower Suit |
| 6 | 2 | Battle Suit |
+----+-------------------+-------------+
6 rows in set (0.00 sec)
JOIN
将包含第一个表的2行和第二个表的6行的所有12个组合:
mysql> SELECT * FROM myapp_armorcategory JOIN myapp_armor;
+----+---------+---------+----+-------------------+-------------+
| id | name | slug | id | armor_category_id | name |
+----+---------+---------+----+-------------------+-------------+
| 1 | Helmets | helmets | 1 | 1 | Dragon Helm |
| 2 | Suits | suits | 1 | 1 | Dragon Helm |
| 1 | Helmets | helmets | 2 | 1 | Duck Helm |
| 2 | Suits | suits | 2 | 1 | Duck Helm |
| 1 | Helmets | helmets | 3 | 1 | Needle Helm |
| 2 | Suits | suits | 3 | 1 | Needle Helm |
| 1 | Helmets | helmets | 4 | 2 | Spiky Suit |
| 2 | Suits | suits | 4 | 2 | Spiky Suit |
| 1 | Helmets | helmets | 5 | 2 | Flower Suit |
| 2 | Suits | suits | 5 | 2 | Flower Suit |
| 1 | Helmets | helmets | 6 | 2 | Battle Suit |
| 2 | Suits | suits | 6 | 2 | Battle Suit |
+----+---------+---------+----+-------------------+-------------+
12 rows in set (0.00 sec)
mysql> SELECT * FROM myapp_armorcategory JOIN myapp_armor
ON myapp_armorcategory.id = myapp_armor.armor_category_id;
+----+---------+---------+----+-------------------+-------------+
| id | name | slug | id | armor_category_id | name |
+----+---------+---------+----+-------------------+-------------+
| 1 | Helmets | helmets | 1 | 1 | Dragon Helm |
| 1 | Helmets | helmets | 2 | 1 | Duck Helm |
| 1 | Helmets | helmets | 3 | 1 | Needle Helm |
| 2 | Suits | suits | 4 | 2 | Spiky Suit |
| 2 | Suits | suits | 5 | 2 | Flower Suit |
| 2 | Suits | suits | 6 | 2 | Battle Suit |
+----+---------+---------+----+-------------------+-------------+
6 rows in set (0.08 sec)
mysql> INSERT INTO myapp_armorcategory (name, slug) VALUES ('Arm Guards', 'armguards');
Query OK, 1 row affected (0.00 sec)
SELECT * FROM myapp_armorcategory JOIN myapp_armor ON myapp_armorcategory.id = myapp_armor.armor_category_id;
),我们将得到相同的结果:新的盔甲类别在盔甲表中没有匹配的记录,因此它不会出现在
JOIN
中。如果我们想查看所有装甲类别都出现在结果中,而不管它们是否在另一个表中有匹配的行,则必须运行一个所谓的
outer join:特别是
LEFT OUTER JOIN
:
mysql> SELECT * FROM myapp_armorcategory LEFT OUTER JOIN myapp_armor
ON myapp_armorcategory.id = myapp_armor.armor_category_id;
+----+------------+-----------+------+-------------------+-------------+
| id | name | slug | id | armor_category_id | name |
+----+------------+-----------+------+-------------------+-------------+
| 1 | Helmets | helmets | 1 | 1 | Dragon Helm |
| 1 | Helmets | helmets | 2 | 1 | Duck Helm |
| 1 | Helmets | helmets | 3 | 1 | Needle Helm |
| 2 | Suits | suits | 4 | 2 | Spiky Suit |
| 2 | Suits | suits | 5 | 2 | Flower Suit |
| 2 | Suits | suits | 6 | 2 | Battle Suit |
| 3 | Arm Guards | armguards | NULL | NULL | NULL |
+----+------------+-----------+------+-------------------+-------------+
7 rows in set (0.00 sec)
NULL
的行。
mysql> INSERT INTO myapp_profile (name) VALUES ('user1');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO myapp_profilearmor (profile_id, armor_id) VALUES (1, 2);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT `myapp_armor`.*, `myapp_profilearmor`.*, T5.*
FROM `myapp_armor`
LEFT OUTER JOIN `myapp_profilearmor`
ON (`myapp_armor`.`id` = `myapp_profilearmor`.`armor_id`)
LEFT OUTER JOIN `myapp_profile` T5
ON (`myapp_profilearmor`.`profile_id` = T5.`id`)
WHERE `myapp_armor`.`armor_category_id` = 1;
+----+-------------------+-------------+------+------------+----------+------+-------+
| id | armor_category_id | name | id | profile_id | armor_id | id | name |
+----+-------------------+-------------+------+------------+----------+------+-------+
| 1 | 1 | Dragon Helm | NULL | NULL | NULL | NULL | NULL |
| 2 | 1 | Duck Helm | 1 | 1 | 1 | 1 | user1 |
| 3 | 1 | Needle Helm | NULL | NULL | NULL | NULL | NULL |
+----+-------------------+-------------+------+------------+----------+------+-------+
3 rows in set (0.04 sec)
(myapp_profilearmor.profile_id = 1 OR T5.id IS NULL)
时,您将从此联接中获取所有行。
mysql> INSERT INTO myapp_profile (name) VALUES ('user2');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO myapp_profilearmor (profile_id, armor_id) VALUES (2, 1);
Query OK, 1 row affected, 1 warning (0.09 sec)
mysql> SELECT `myapp_armor`.*, `myapp_profilearmor`.*, T5.*
FROM `myapp_armor`
LEFT OUTER JOIN `myapp_profilearmor`
ON (`myapp_armor`.`id` = `myapp_profilearmor`.`armor_id`)
LEFT OUTER JOIN `myapp_profile` T5
ON (`myapp_profilearmor`.`profile_id` = T5.`id`)
WHERE `myapp_armor`.`armor_category_id` = 1;
+----+-------------------+-------------+------+------------+----------+------+-------+
| id | armor_category_id | name | id | profile_id | armor_id | id | name |
+----+-------------------+-------------+------+------------+----------+------+-------+
| 1 | 1 | Dragon Helm | 2 | 2 | 1 | 2 | user2 |
| 2 | 1 | Duck Helm | 1 | 1 | 2 | 1 | user1 |
| 3 | 1 | Needle Helm | NULL | NULL | NULL | NULL | NULL |
+----+-------------------+-------------+------+------------+----------+------+-------+
3 rows in set (0.00 sec)
(myapp_profilearmor.profile_id = 2 OR T5.id IS NULL)
,这将仅选择第1行和第3行。第2行将丢失。
Q(profilearmor__profile=None)
成为了子句
T5.id IS NULL
,这仅选择
ProfileArmor
关系中没有条目(对于任何配置文件)的行。
count()
方法测试配置文件是否可以访问类别中的任何类型的装甲:if self.armor_category.armor_set.filter(
profilearmor__profile=self.request.user.profile
).count() == 0:
exists()
方法。 ManyToManyField
模型上设置Armor
,为什么不使用它呢?也就是说,不是像这样查询Armor
模型:Q(profilearmor__profile = ...)
Q(profile = ...)
关于django - 用Count注释无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15698866/
所以`MKAnnotation's。有趣的东西。 我的问题: 注释的标题和副标题有什么区别?这对注释的视觉组件有何影响? MKPinAnnotationView 和 MKAnnotationView
我正在使用 JBoss 工具将 DB 模式反向工程到 POJO 中。具体来说,我在 hibernatetool ANT 任务中使用了 hbm2java 选项。在 hbm2java 选项下,您可以指定
假设我有这段文字: cat file /* comment */ not a comment /* another comment */ /* delete this * /* multiline
我明白,如果你///在类、字段、方法或属性上方 Visual Studio 将开始为您建立 XML 样式的注释。 但是,我在哪里可以为我的命名空间和/或库添加 XML 注释... 例如: .NET F
int API_VERSION = 21; @TargetApi(API_VERSION)在Android中用于指定该方法/类支持API_VERSION及以下。 我们是否可以镜像类似的东西,指定仅支持
Closed. This question needs to be more focused。它当前不接受答案。
假设我有一个界面如下。 public interface MyInterface{ /** * This method prints hello */ void sayHello();
我已将 Jboss 应用程序迁移到 WebSphere Liberty。我必须删除所有 Jboss 引用库。在这样做的同时,我在某些注释中面临问题。 Jboss 应用程序使用 @SecurityDom
在本教程中,您将了解 JavaScript 注释,为什么要使用它们以及在示例的帮助下如何使用它们。 JavaScript 注释是程序员可以添加的提示,以使代码更易于阅读和理解。JavaScri
我正在建立一个博客,为了发表评论,我有这个 CSS。 #comments { position:absolute; border: 1px solid #900; border-width: 1
我正在尝试在单元格中插入评论。我正在尝试按照代码进行评论,但它没有在创建的 excel 中显示评论。我正在创建 .xls 扩展名。 $objPHPExcel->getActiveSheet()->ge
我正在使用 TS 在 MarionetteJS 上编写项目,我想使用注释来注册路由。例如: @Controller class SomeController { @RouteMapping("so
我有一个应用程序可以在页面上生成大量注释。用户可以单击页面上的任意位置以创建快速注释(例如 Acrobat Pro)可以在一般 中使用一些 javascript 行添加和删除这些注释
是否有 JavaScript 注释? 当然 JavaScript 没有它们,但是是否有额外的库或建议的语言扩展,例如 @type {folder.otherjsmodule.foo} function
Java 中注解的目的是什么?我有一个模糊的想法,认为它们介于注释和实际代码之间。它们在运行时会影响程序吗? 它们的典型用法是什么? 它们是 Java 独有的吗?有 C++ 等价物吗? 最佳答案 注解
其实我们在 Ruby 基础语法 已经比较详细的介绍了 Ruby 语言中的注释 Ruby 解释器会忽略注释语句 注释会对 Ruby 解释器隐藏一行,或者一行的一部分,或者若干行。 Ruby 中的注
我正在 try catch VBA 注释。到目前为止,我有以下内容 '[^";]+\Z 它捕获以单引号开头但在字符串结尾之前不包含任何双引号的任何内容。即它不会匹配双引号字符串中的单引号。 dim s
有没有办法在'svn commit'上将提交注释添加到更改的文件中。有人告诉我有一种方法可以用 cvs 做到这一点,但我们使用 svn。目前,我们使用“$Revision”关键字将修订号添加到更改的文
我正在尝试通过 ManyToMany 注释自动对报告的结果进行排序 @OrderBy : /** * @ORM\ManyToMany(targetEntity="Artist", inversedB
我正在使用 JBoss 5 GA,我创建了一个测试 session bean 和本地接口(interface)。我创建了一个 servlet 客户端。我尝试使用 @EJB 将接口(interface)
我是一名优秀的程序员,十分优秀!