Rob*_*bin 7 django django-models django-queryset django-rest-framework
我创建了一个应用程序,用户可以在其中发布相关标签:
class Tag(models.Model):
name = models.CharField(max_length=255, unique=True)
class Post(models.Model):
user = models.ForeignKey(User)
body = models.TextField()
tags = models.ManyToManyField(Tag)
pub_date = models.DateTimeField(default=timezone.now)
activity = GenericRelation(Activity, related_query_name="posts")
class Photo(models.Model):
user = models.ForeignKey(User)
file = models.ImageField()
tags = models.ManyToManyField(Tag)
pub_date = models.DateTimeField(default=timezone.now)
activity = GenericRelation(Activity, related_query_name="photos")
class Activity(models.Model):
actor = models.ForeignKey(User)
verb = models.PositiveIntegerField(choices=VERB_TYPE)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
pub_date = models.DateTimeField(default=timezone.now)
Run Code Online (Sandbox Code Playgroud)
我想要做的是获取/过滤最多5个最新/最近的Activity对象,用户列表,以及Post对象标签列表中的标签列表,并使用django-rest-framework返回json进行查看客户方.
例如活动:
所以说我想用user_list=[UserA, UserC]和过滤Activitytag_list = [#class, #teacher]
它应该返回:
要使用用户过滤活动,我可以这样查询:
Activity.objects.filter(actor__in=user_list)
Run Code Online (Sandbox Code Playgroud)
但是,如何使用content_object(iePost或Photo)字段(即Post.tags或Photo.tags)过滤Activity?现在我这样做:
Activity.objects.filter(posts__tags__in=tag_l)
Activity.objects.filter(photos__tags__in=tags)
Run Code Online (Sandbox Code Playgroud)
总而言之,如果我需要有用户列表和标签列表的活动,我必须这样做:
activites = Activity.objects.filter(
Q(actor__in=user_list) |
Qposts__tags__in=tag_list) |
Q(photos__tags__in=tag_list)
)
Run Code Online (Sandbox Code Playgroud)
但是假设将有两个以上的ContentType模型类,那么我将不得不再次添加另一个Q(moreModel__tags__in=tag_list).所以,我希望有一种更好的方法来优化这个过程.
我会给你一个django updown的例子,它有一个类似的模型: https: //github.com/weluse/django-updown/blob/master/updown/models.py#L31
>>> from updown.models import Vote
>>> Vote.objects.first()
<Vote: john voted 1 on Conveniently develop impactful e-commerce>
>>> v = Vote.objects.first()
>>> v.content_object
<Thread: Conveniently develop impactful e-commerce>
>>> v.content_object.__class__
<class 'app_forum.models.Thread'>
>>> [ v.content_type for v in Vote.objects.all() if v.content_object.__class__.__name__ == 'Thread' ]
[<Thread: Conveniently develop impactful e-commerce>, <Thread: Quickly evisculate exceptional paradigms>]
>>>
# You can also use with
>>> user_ids = [ u.content_type.id for u in Vote.objects.all() if u.content_object.__class__.__name__ == 'User' ]
>>> user_ids
[1, 52, 3, 4]
>>> from django.contrib.auth.models import User
>>> User.objects.filter(pk__in=user_ids)
[<User: John>, <User: Alex>, <User: Roboto>, <User: Membra>]
>>>
>>> from django.contrib.contenttypes.models import ContentType
>>> ContentType.objects.get_for_model(v.content_object)
<ContentType: Detail Thread>
>>>
Run Code Online (Sandbox Code Playgroud)
您也可以使用ContentType.objects.get_for_model(model_instance)这样的: https: //github.com/weluse/django-updown/blob/master/updown/fields.py#L70
在你的问题中,也许可以用这个..
>>> photo_ids = [ ac.content_type.id for ac in Activity.objects.all() if ac.content_object.__class__.__name__ == 'Photo' ]
>>> Activity.objects.filter(content_type__id__in=photo_ids)
# or
>>> photo_ids = [ ac.content_type.id for ac in Activity.objects.all() if content_type.model_class().__name__ == 'Photo']
>>> Activity.objects.filter(content_type__id__in=photo_ids)
Run Code Online (Sandbox Code Playgroud)
希望它能有所帮助..
| 归档时间: |
|
| 查看次数: |
1748 次 |
| 最近记录: |