【问题标题】:Querying model field data in template/views without get_object_or_404()在没有 get_object_or_404() 的情况下查询模板/视图中的模型字段数据
【发布时间】:2021-05-01 00:38:25
【问题描述】:

Homefeed 是我查询所有博文的页面

在这个项目中,任何看到他们感兴趣的博文的用户都可以将他们的兴趣提交给博文。 1 位用户只能对该博文提交 1 个兴趣,但他们可以向不同的博文提交任意数量的兴趣。

现在在我的 home.html 中,我正在尝试使如果您已提交对该特定博客文章的兴趣(也就是您的兴趣状态为待处理或接受或拒绝),您将看到查看兴趣按钮而不是提交兴趣按钮。

但我面临一个问题,因为在我看来,我查询的是blog_posts = BlogPost.objects.all() 而不是blog_post = get_object_or_404(BlogPost, slug=slug)。因此,我如何能够查询对于特定的博文,用户是否已经提交了对我的模板的兴趣以确定应该在我的 home.html 中显示哪个按钮?谢谢,我也不想更改网址:)

views.py

def home_feed_view(request, *args, **kwargs):
    context = {}
    blog_posts = BlogPost.objects.all()
    context['blog_posts'] = blog_posts 
    page = pageFilter(request.GET, queryset=BlogPost.objects.exclude(author_id=request.user.id).order_by('date_updated')) 
    context['page'] = page
    paginated_page = Paginator(page.qs, 4)
    page = request.GET.get('page')
    page_obj = paginated_page.get_page(page)

    context['page_obj'] = page_obj
    return render(request, "HomeFeed/snippets/home.html", context)

home.html

{% for post in page_obj %}

{% if post.interest_set.exists and request.user.is_authenticated %}

     <a class="btn btn-info btn-sm" href="{% url 'HomeFeed:submitinterest' post.slug %}">View Interest</a>
     {% else %}  
      <a class="btn btn-warning btn-sm" href="{% url 'HomeFeed:submitinterest' post.slug %}">Submit Interest</a>
      {% endif %}
      {% endfor %}

urls.py

path('', home_feed_view , name= "main"),

models.py

class Account(AbstractBaseUser):
 email                  = models.EmailField(verbose_name="email", max_length=60, unique=True)
 username               = models.CharField(max_length=30, unique=True)

class BlogPost(models.Model):
 title                  = models.CharField(max_length=50, null=False, blank=False, unique=True)
 author                     = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
 slug                   = models.SlugField(blank=True, unique=True)

class Interest(models.Model):
   user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
   blog_post = models.ForeignKey(BlogPost, on_delete=models.CASCADE)

class InterestInvite(models.Model):

   ACCEPT = "ACCEPT"
   DECLINE = "DECLINE"
   PENDING = "PENDING"
   STATUS_CHOICES = [
      (ACCEPT, "accept"),
      (DECLINE, "decline"),
      (PENDING, "pending"),

   ]

   interest = models.OneToOneField(Interest, on_delete=models.CASCADE, related_name="interest_invite")   
   status = models.CharField(max_length=25, choices=STATUS_CHOICES, default=PENDING)
   objects= models.Manager

views.py

        type = TypeFilter(request.GET, queryset=BlogPost.objects.exclude((Q(author_id__in=request.user.blocked_users.all()) | Q(author = request.user))).order_by('date_updated')).annotate(user_has_interest=Case(When(interest__user=request.user, then=Value(True)), default=False, output_field=BooleanField()))

使用 Django 过滤器: 过滤器.py

class TypeofIdeaFilter(django_filters.FilterSet):
    title = django_filters.CharFilter(field_name="title", lookup_expr='icontains')

    class Meta:
        model = BlogPost

【问题讨论】:

    标签: django django-models django-views django-forms django-templates


    【解决方案1】:

    您可以在查询中注释字段:

    from django.db.models import Case, When, Value, BooleanField
    
    blog_posts = BlogPost.objects.all().annotate(
        user_has_interest=Case(When(interest__user=request.user, then=Value(True)), default=False, output_field=BooleanField())
    )
    

    现在您可以使用 if-else 签入模板:

    {% if post.user_has_interest %}
        Something
    {% else %}
        Something else
    {% endif %}
    

    【讨论】:

    • 嗨兄弟,让我让它更具挑战性,如果我使用过滤器怎么办?那么我将无法使用注释@AbdulAzizBarkat(我已经编辑了下面的代码供您查看..因为使用注释会给我一个属性错误
    • @hoehoehoe 只需覆盖 Filterset 的 qs 属性并在此处注释 Filtering the primary - Django Filter
    • 谢谢你!抱歉,您介意更新代码以防我误解文档:)
    • @hoehoehoe 这个问题与原来的问题不同,因此在这里回答是不正确的。请看Update a question or post a new question?
    【解决方案2】:

    As Pierre mentioned 模板标签也实现了这一点(alternate for annotate Abdul 回答)。

    首先创建文件结构。进入需要标签的app目录,添加以下文件:

    templatetags
    templatetags/__init__.py
    templatetags/blog_tags.py
    

    templatetags/blog_tags.py 文件:

    from django import template
    
    register = template.Library()
    
    @register.simple_tag
    def interest_submitted(blog_id, user_id):
        if Interest.objects.filter(blog_post__id=blog_id, user_id=user_id).exists():
            return True
        else:
            return False
    

    在模板中:

    {% load blog_tags %} <!--don't forget to load the blog_tags.py file in the template. -->
    
    {% for post in page_obj %}
    {% interest_submitted post.id request.user.id as result %}
    {% if result and request.user.is_authenticated %}
        <a class="btn btn-info btn-sm" href="{% url 'HomeFeed:submitinterest' post.slug %}">View Interest</a>
    {% else %}  
        <a class="btn btn-warning btn-sm" href="{% url 'HomeFeed:submitinterest' post.slug %}">Submit Interest</a>
    {% endif %}
    {% endfor %}
    

    【讨论】:

      【解决方案3】:

      您可以使用 try 代替 get_object_or_404()。这样,如果对象不存在,您可以使用不同的逻辑并返回不同的上下文

      伪代码:

      context = {}
          try:
             blog_posts = BlogPost.objects.all()
             ...
             context = "Something"
             return render(request, "HomeFeed/snippets/home.html", context)
          
          except BlogPost.DoesNotExist:
             context = "Something else"
             return render(request, "HomeFeed/snippets/home.html", context)
      

      【讨论】:

        猜你喜欢
        • 2012-01-22
        • 2017-04-26
        • 2021-05-10
        • 1970-01-01
        • 2018-12-11
        • 1970-01-01
        • 1970-01-01
        • 2015-05-22
        • 1970-01-01
        相关资源
        最近更新 更多