如何使用父字段限制查询集?

时间:2015-12-27 06:15:37

标签: python django django-queryset

我要通过父模型字段限制。

models.py

class Blog(Model):
    max_posts       = IntegerField(verbose_name=u"Limite Posts", help_text=u"Número de posts máximo DESSE BLOG para serem exibidos na home.")

class Post(Model):
    title           = CharField(max_length=200, verbose_name=u"Título")

我想在我的模板上得到类似的内容:

- 博客A(max_posts = 2)

Item 1

Item 2

- 博客B(max_posts = 3)

Item 1

Item 2

Item 3

所以我在我的观点上尝试了这个

views.py

Post.objects.annotate(blog__max_posts=Count('blog__max_posts')).filter(blog__published=True)

但它不像预期的那样有效。我怎么能这样做?

3 个答案:

答案 0 :(得分:1)

如果添加缺少的外键:

class Blog(Model):
    name = CharField(max_length=255)
    max_posts = IntegerField(verbose_name=u"Limite Posts", help_text=u"Número de posts máximo DESSE BLOG para serem exibidos na home.")

class Post(Model):
    blog = ForeignKey(Blog)
    title = CharField(max_length=200, verbose_name=u"Título")

你可以通过每个博客一个db-hit获取帖子:

blogs = Blog.objects.filter(published=True)
posts = {b:b.post_set.all()[:b.max_posts] for b in blogs}

您可能希望在切片前添加order_by ..

然后,模板可以是写成:

{% for blog, blogposts in posts.items %}
    <h1>{{ blog.name }} (max_posts={{ blog.max_posts }})</h1>
    <ul>
    {% for post in blogposts %}
       <li>{{ post }}</li>  {# probably something more fancy here.. #}
    {% endfor %}
    </ul>
{% endfor %}

答案 1 :(得分:0)

不确定django是否为您提供了这样的内置功能,因此您需要自己处理它。为此,在ForeignKey模型中定义Blog关系:

class Blog(Model):
  # Other fields 
  post = models.ForeignKey(Post)

通过向add_post模型添加Blog方法来实现所需的结果:

def add_post(self, post):
    # assume you have max_posts_count defined
    if self.post_set.count() >= max_posts_count:
         raise Exception("Too many posts")

    self.post_set.add(post)

获得相同结果的其他方法是使用Django pre_save signal检查posts计数是否达到最大值,如果它在pre_save方法中raise Exception或允许保存。

答案 2 :(得分:0)

  

在Post上放置一个与Blog相关的ForeignKey字段。

     

在该字段validate_max_posts上使用验证器,如下所示:

from django.core.exceptions import ValidationError

class Blog(Model):
    max_posts = IntegerField(verbose_name=u"Limite Posts", help_text=u"Número de posts máximo DESSE BLOG para serem exibidos na home.")

def validate_max_posts(value):
    blog_id = None
    if type(value) is not Blog:   # admin panel
        blog_id = value

    if type(value) is Blog:       # service : DRF
        blog_id = value.id

    post_count = Post.objects.filter(blog__id = blog_id).count()
    max_posts = Blog.objects.get(pk=blog_id)
    if post_count > max_posts:
        raise ValidationError(u'Exceed max posts count')

class Post(Model):
    title = CharField(max_length=200, verbose_name=u"Título")
    blog = models.ForeignKey(Blog,validators=[validate_max_posts])