在我的数据库中,我有一个Photo
类,我用它作为其他类的外键。这是两个例子。
class SubstancePointsLabel(ResultBase):
#: photo being labeled
photo = models.ForeignKey(Photo, related_name='substance_points_labels')
class SubstancePoint(EmptyModelBase):
#: photo
photo = models.ForeignKey(Photo, related_name='substance_points')
ResultBase
和EmptyModelBase
这些实例的唯一区别似乎是(对我而言)是原因。
class EmptyModelBase(models.Model):
""" Base class of all models, with no fields """
def get_entry_dict(self):
return {'id': self.id}
def get_entry_attr(self):
ct = ContentType.objects.get_for_model(self)
return 'data-model="%s/%s" data-id="%s"' % (
ct.app_label, ct.model, self.id)
def get_entry_id(self):
ct = ContentType.objects.get_for_model(self)
return '%s.%s.%s' % (ct.app_label, ct.model, self.id)
class Meta:
abstract = True
ordering = ['-id']
class ResultBase(UserBase):
""" Base class for objects created as a result of a submission """
#: The MTurk Assignment that the user was in when this record was created
mturk_assignment = models.ForeignKey(
'mturk.MtAssignment', null=True, blank=True,
related_name='+', on_delete=models.SET_NULL
)
#: True if created in the mturk sandbox
sandbox = models.BooleanField(default=False)
#: This has been marked by an admin as invalid or incorrect AND will be
#: re-scheduled for new labeling. This can happen when an experiment is
#: changed and things need to be recomputed.
invalid = models.BooleanField(default=False)
#: The method by which the quality label was obtained
QUALITY_METHODS = (
('A', 'admin'), ('C', 'CUBAM'),
('M', 'majority vote'), ('Q', 'qualification'),
('S', 'seed point'),
)
quality_method_to_str = dict((k, v) for (k, v) in QUALITY_METHODS)
#: The method by which the quality label was obtained
quality_method = models.CharField(
max_length=1, choices=QUALITY_METHODS, blank=True, null=True)
#: time taken to specify this label in ms
time_ms = models.IntegerField(blank=True, null=True, db_index=True)
#: time taken to specify this label in ms, excluding time that the user was
#: in another window
time_active_ms = models.IntegerField(blank=True, null=True, db_index=True)
#: payment for this specific label
reward = models.DecimalField(
decimal_places=4, max_digits=8, null=True, blank=True)
def save(self, *args, **kwargs):
if not self.id and self.mturk_assignment:
self.sandbox = self.mturk_assignment.hit.sandbox
if not self.reward:
from common.utils import compute_label_reward
self.reward = compute_label_reward(self)
super(ResultBase, self).save(*args, **kwargs)
def time_s(self):
""" Time pretty-printed in seconds (helper for templates) """
if self.time_ms:
t = self.time_ms / 1000.0
return round(t, 2 if t < 10 else 1)
else:
return None
def time_active_s(self):
""" Active pretty-printed time in seconds (helper for templates) """
if self.time_active_ms:
t = self.time_active_ms / 1000.0
return round(t, 2 if t < 10 else 1)
else:
return None
def mark_invalid(self, save=True):
dirty = (not self.invalid)
self.invalid = True
self.quality_method = 'A'
if save:
self.save()
if dirty:
marked_invalid.send(sender=self.__class__, instance=self)
def get_thumb_overlay(self):
return self.__unicode__()
class Meta:
abstract = True
ordering = ['-time_ms']
对于Photo实例,我能够通过相关名称访问SubstancePointsLabel
和SubstancePoint
。
In : photo.substance_points_labels.count()
Out: 3
In : photo.substance_points.count()
Out: 9
我希望过滤Photo实例,关于相关类是否存在,我的操作如下。
In : Photo.objects.filter(substance_exists_labels__exists=True).count()
Out: 335932
现在,如上所述,这适用于某些人。对于其他几个,查询返回错误:
In : Photo.objects.filter(substance_points__exists=True).count()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/data_nfs/opensurfaces2/server/matclass/tasks.pyc in <module>()
----> 1 Photo.objects.filter(substance_points__exists=True).count()
/data_nfs/opensurfaces2/venv/local/lib/python2.7/site-packages/django/db/models/manager.pyc in manager_method(self, *args, **kwargs)
90 def create_method(name, method):
91 def manager_method(self, *args, **kwargs):
---> 92 return getattr(self.get_queryset(), name)(*args, **kwargs)
93 manager_method.__name__ = method.__name__
94 manager_method.__doc__ = method.__doc__
/data_nfs/opensurfaces2/venv/local/lib/python2.7/site-packages/django/db/models/query.pyc in filter(self, *args, **kwargs)
689 set.
690 """
--> 691 return self._filter_or_exclude(False, *args, **kwargs)
692
693 def exclude(self, *args, **kwargs):
/data_nfs/opensurfaces2/venv/local/lib/python2.7/site-packages/django/db/models/query.pyc in _filter_or_exclude(self, negate, *args, **kwargs)
707 clone.query.add_q(~Q(*args, **kwargs))
708 else:
--> 709 clone.query.add_q(Q(*args, **kwargs))
710 return clone
711
/data_nfs/opensurfaces2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.pyc in add_q(self, q_object)
1329 existing_inner = set(
1330 (a for a in self.alias_map if self.alias_map[a].join_type == self.INNER))
-> 1331 clause, require_inner = self._add_q(where_part, self.used_aliases)
1332 self.where.add(clause, AND)
1333 for hp in having_parts:
/data_nfs/opensurfaces2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.pyc in _add_q(self, q_object, used_aliases, branch_negated, current_negated)
1356 child_clause, needed_inner = self.build_filter(
1357 child, can_reuse=used_aliases, branch_negated=branch_negated,
-> 1358 current_negated=current_negated, connector=connector)
1359 joinpromoter.add_votes(needed_inner)
1360 target_clause.add(child_clause, connector)
/data_nfs/opensurfaces2/venv/local/lib/python2.7/site-packages/django/db/models/sql/query.pyc in build_filter(self, filter_expr, branch_negated, current_negated, can_reuse, connector)
1223 # refactored when composite fields lands.
1224 condition = field.get_lookup_constraint(self.where_class, alias, targets, sources,
-> 1225 lookups, value)
1226 lookup_type = lookups[-1]
1227 else:
/data_nfs/opensurfaces2/venv/local/lib/python2.7/site-packages/django/db/models/fields/related.pyc in get_lookup_constraint(self, constraint_class, alias, targets, sources, lookups, raw_value)
1575 root_constraint.add(value_constraint, OR)
1576 else:
-> 1577 raise TypeError('Related Field got invalid lookup: %s' % lookup_type)
1578 return root_constraint
1579
TypeError: Related Field got invalid lookup: exists
以相同的方式创建类,并以相同的方式查询。它可能导致某些情况下的错误,而不是其他情况?
答案 0 :(得分:2)
您可以使用exclude
方法和__isnull
查找来完成此操作。
Photo.objects.exclude(substance_points__isnull=True).count()
或者您可以使用 conditional expression
from django.db.models import When, Case, IntegerField
Photo.objects.annotate(
has_substance_points=Case(
When(
substance_points__isnull=True, then=0
),
default=1,
output_field=IntegerField()
)
).filter(has_substance_points=1).count()
以上查询将返回照片数量 的 substance_points 强>
<强>更新强>
或者,如果您只想要拥有substance_points
的照片数量,您还可以考虑以下方法。
SubstancePoint.objects.all().order_by('photo_id').distinct('photo_id').count()
# Query will return count of photos that has substance_points
答案 1 :(得分:0)
在Django的字段查找中是否真的有类似“__exists”的东西?使用“__isnull”有一种简单的方法可以做到这一点。而不是:
Photo.objects.filter(substance_points__exists=True).count()
你可以:
Photo.objects.filter(substance_points__isnull=False).count()