django - 按模型的不同字段过滤 class
django - Filter by distinct fields of a model class
我有一个用户活动模型:
class Activity(models.Model):
actor = models.ForeignKey(User)
action = models.CharField(max_length=100)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
class Meta:
verbose_name = 'Activity'
verbose_name_plural = 'Activities'
ordering = ['-pub_date']
def __unicode__(self):
return ("%s %s") % (self.actor.username, self.action)
观看次数:
def home(request):
if request.user.is_authenticated():
user = request.user
userP = Person.objects.get_or_create(user=user)
userP = userP[0]
following = userP.get_following()
users = []
actors = list(following.values_list('user', flat=True)) + [user.id]
activities = Activity.objects.filter(actor__in=actors)
更新
假设有 3 个用户喜欢相同的状态,而用户 3 是最后一个喜欢该状态的人。现在将创建 3 个活动,分别为 "User1 liked status"、"User2 liked status"、"User3 liked status"。我想要的是每个状态只得到一个 activity,这是最近的一个。所以在这种情况下它将是 "User3 liked status".
状态模型:
class Status(models.Model):
body = models.TextField(max_length=200)
image = models.ImageField(blank=True, null=True, upload_to=get_upload_file_name)
privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
user = models.ForeignKey(User)
hearts = generic.GenericRelation(Heart, null=True, blank=True)
class Heart(models.Model):
user = models.ForeignKey(User)
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
更新
这是signals.py为每个对象(心或状态)创建activity:
def create_activity_item(sender, instance, signal, *args, **kwargs):
if kwargs.get('created', True):
ctype = ContentType.objects.get_for_model(instance)
if ctype.name == 'Status':
action = ' shared '
activity = Activity.objects.get_or_create(
actor = instance.user,
action = action,
content_type = ctype,
object_id = instance.id,
pub_date = instance.pub_date
)
if ctype.name == 'Heart':
action = ' gave heart to '
activity = Activity.objects.get_or_create(
actor = instance.user,
action = action,
content_type = ctype,
object_id = instance.id,
pub_date = instance.pub_date
)
for modelname in [Status, Heart]:
post_save.connect(create_activity_item, sender=modelname,
dispatch_uid="create_activity_item")
activities = Activity.objects.filter(actor__in=users).distinct('content_type', 'object_id', 'action')
如果您的数据库不支持 DISTINCT ON
查询,您可以进行查询,然后通过对象手动 运行 查找不同的值:
unique_activities = []
activities = Activity.objects.filter(actor__in=users)
for activity in activities:
unseen = True
for unique_activity in unique_activities:
if (activity.action == unique_activity.action and activity.content_type == unique_activity.content_type and activity.object_id == unique_activity.object_id):
unseen = False
break
if unseen:
unique_activities.append(activity)
print unique_activities
这听起来像是一个 greatest-per-group
问题。你能试试这个吗:
activities = Activity.objects.filter(
id__in=Activity.objects.values('content_type') \
.annotate(max_id=Max('id')) \
.values_list('max_id', flat=True) \
)
这仅适用于 PostgreSQL:
Activity.objects.order_by('action', 'content_type_id', 'object_id', '-pub_date').distinct('action', 'content_type_id', 'object_id').filter(actor__in=actors)
我有一个用户活动模型:
class Activity(models.Model):
actor = models.ForeignKey(User)
action = models.CharField(max_length=100)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
class Meta:
verbose_name = 'Activity'
verbose_name_plural = 'Activities'
ordering = ['-pub_date']
def __unicode__(self):
return ("%s %s") % (self.actor.username, self.action)
观看次数:
def home(request):
if request.user.is_authenticated():
user = request.user
userP = Person.objects.get_or_create(user=user)
userP = userP[0]
following = userP.get_following()
users = []
actors = list(following.values_list('user', flat=True)) + [user.id]
activities = Activity.objects.filter(actor__in=actors)
更新
假设有 3 个用户喜欢相同的状态,而用户 3 是最后一个喜欢该状态的人。现在将创建 3 个活动,分别为 "User1 liked status"、"User2 liked status"、"User3 liked status"。我想要的是每个状态只得到一个 activity,这是最近的一个。所以在这种情况下它将是 "User3 liked status".
状态模型:
class Status(models.Model):
body = models.TextField(max_length=200)
image = models.ImageField(blank=True, null=True, upload_to=get_upload_file_name)
privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
user = models.ForeignKey(User)
hearts = generic.GenericRelation(Heart, null=True, blank=True)
class Heart(models.Model):
user = models.ForeignKey(User)
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
更新
这是signals.py为每个对象(心或状态)创建activity:
def create_activity_item(sender, instance, signal, *args, **kwargs):
if kwargs.get('created', True):
ctype = ContentType.objects.get_for_model(instance)
if ctype.name == 'Status':
action = ' shared '
activity = Activity.objects.get_or_create(
actor = instance.user,
action = action,
content_type = ctype,
object_id = instance.id,
pub_date = instance.pub_date
)
if ctype.name == 'Heart':
action = ' gave heart to '
activity = Activity.objects.get_or_create(
actor = instance.user,
action = action,
content_type = ctype,
object_id = instance.id,
pub_date = instance.pub_date
)
for modelname in [Status, Heart]:
post_save.connect(create_activity_item, sender=modelname,
dispatch_uid="create_activity_item")
activities = Activity.objects.filter(actor__in=users).distinct('content_type', 'object_id', 'action')
如果您的数据库不支持 DISTINCT ON
查询,您可以进行查询,然后通过对象手动 运行 查找不同的值:
unique_activities = []
activities = Activity.objects.filter(actor__in=users)
for activity in activities:
unseen = True
for unique_activity in unique_activities:
if (activity.action == unique_activity.action and activity.content_type == unique_activity.content_type and activity.object_id == unique_activity.object_id):
unseen = False
break
if unseen:
unique_activities.append(activity)
print unique_activities
这听起来像是一个 greatest-per-group
问题。你能试试这个吗:
activities = Activity.objects.filter(
id__in=Activity.objects.values('content_type') \
.annotate(max_id=Max('id')) \
.values_list('max_id', flat=True) \
)
这仅适用于 PostgreSQL:
Activity.objects.order_by('action', 'content_type_id', 'object_id', '-pub_date').distinct('action', 'content_type_id', 'object_id').filter(actor__in=actors)