Как исправить 'Значение QuerySet для точного поиска должно быть ограничено одним результатом с использованием срезов.' ошибка в Джанго - PullRequest
1 голос
/ 24 мая 2019

Я пытаюсь вернуть количество отфильтрованных qweryset в моих представлениях Django.Как мне добиться этого, избегая при этом «Значение QuerySet для точного поиска должно быть ограничено одним результатом с использованием срезов».ошибка?

Я пытался использовать len (), но все равно получаю ту же ошибку.

Это мой код:

models

class Post(models.Model):
    STATUS_CHOICES = (
        ('draft', 'Draft'),
        ('published', 'Published'),
    )

    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200)
    author = models.ForeignKey(settings.AUTH_USER_MODEL, 
                              on_delete=models.CASCADE)
    body = models.TextField()
    category = models.ForeignKey(Category, on_delete=models.CASCADE, 
                                  blank=True, null=True)
    read_time = models.CharField(max_length=256, null=True, blank=True)
    count_visits = models.IntegerField(default=0)
    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, 
                              default='published')

    class Meta:
        ordering = ('-publish',)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('blog:blog_post', args=[self.slug])

    def get_body_as_markdown(self):
        return mark_safe(markdown(self.body, safe_mode='escape'))

class PostView(models.Model):
    post = models.ForeignKey(Post, on_delete=models.SET_NULL, null=True,
                             related_name='postviews')
    ip = models.CharField(max_length=50)
    http_host = models.CharField(max_length=256, null=True, blank=True)
    http_referrer = models.CharField(max_length=256, null=True, blank=True)
    http_user_agent = models.CharField(max_length=256, null=True, blank=True)
    remote_host = models.CharField(max_length=256, null=True, blank=True)

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.ip

views:

class PostDetailView(DetailView):
    model = Post
    template_name = 'blog/post.html'
    context_object_name = 'post'

    def get(self, request, *args, **kwargs):
        self.slug = get_object_or_404(Post, slug=self.kwargs['slug'])
        p = Post.objects.filter(slug=self.slug)
        count_visits = None
        unique_views = set()

        if self.request.user.is_authenticated:
            post_views = PostView.objects.filter(post=p)
            count_visits = post_views.count()
            for post_view in post_views:
                unique_views.add(post_view.ip)

        else:
            post_view = PostView(ip=request.META.get('REMOTE_ADDR', ''),
                      http_host=request.META.get('HTTP_HOST', ''),                             
                      http_referrer=request.META.get('HTTP_REFERER',''),                               
                      http_user_agent=request.META.get('HTTP_USER_AGENT',''),
                      remote_host=request.META.get('REMOTE_HOST', ''))

            post_view.save()

        c = {
            'count_visits': count_visits,
            'unique_views': unique_views,
        }
        return render(request, self.template_name, c)

template:

<span>
    {% if user.is_authenticated %}
      <br>
      {{ count_visits }} views, {{ unique_views|length }} unique views.
    {% endif %}
</span>

Я ожидаю, что вывод покажет количество просмотров в шаблоне, но я получаю значение "QuerySet дляточный поиск должен быть ограничен одним результатом с использованием нарезки. "ошибка.

Большое спасибо!

1 Ответ

2 голосов
/ 24 мая 2019

Изменить это

p = Post.objects.filter(slug=self.slug)

К этому

p = Post.objects.filter(slug=self.slug)[0]

ОШИБКА:

filter возвращает набор запросов, даже если соответствует только один элемент.

PostView.objects.filter(post=p) завершается неудачно, поскольку ожидает, что сообщение будет объектом, а не набором запросов.

ОБНОВЛЕНИЕ:

self.slug не будет инициализирован, поскольку переменные экземпляра могут быть объявлены только внутри __init__.

Вы можете просто удалить деталь self, чтобы пометить slug как локальную переменную вместо

slug = get_object_or_404(Post, slug=self.kwargs['slug'])
p = Post.objects.filter(slug=slug)
...