Представление класса Django - ошибка MultipleObjectsReturned - PullRequest
1 голос
/ 18 марта 2019

Я все еще новичок в Джанго, поэтому, пожалуйста, потерпите меня.Я пытаюсь сделать сайт о книгах.Теперь у меня появляется ошибка, подобная этой

MultipleObjectsReturned в / premium / 1 / get () вернул более одной книги - она ​​вернула 2!

Не знаюне знаю, где искать ошибку.Вот мой пример кода.

class PageDetailView(LoginRequiredMixin, generic.View):

    def get(self, request, *args, **kwargs):
        book = get_object_or_404(Book)
        page = get_object_or_404(Page)
        user_membership = get_object_or_404(Customer, user=request.user)
        user_membership_type = user_membership.membership.membership_type
        user_allowed = book.allowedMembership.all()
        context = {'object': None}
        if user_allowed.filter(membership_type=user_membership_type).exists():
            context = {'object': page}
        return render(request, "catalog/page_detail.html", context)

Трассировка:

Файл "C: \ Users \ admin \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ site-packages \ django \ core \ handlers \ exception.py "во внутреннем 34. response = get_response (запрос)

Файл" C: \ Users \ admin \ AppData \ Local \ Programs \ Python \ Python37-32 \ "lib \ site-packages \ django \ core \ handlers \ base.py "в _get_response 126. response = self.process_exception_by_middleware (e, запрос)

Файл" C: \ Users \ admin \ AppData \ Local \ Programs\ Python \ Python37-32 \ lib \ site-packages \ django \ core \ handlers \ base.py "в _get_response 124. response = wrapped_callback (запрос, * callback_args, ** callback_kwargs)

Файл" C:\ Users \ admin \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ site-packages \ django \ views \ generic \ base.py "в представлении 68. вернуть self.dispatch (request, * args, ** kwargs))

Файл "C: \ Users \ admin \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ site-packages \ django \ contrib \ auth \ mixins.py" в отправке 52. вернуть super() .dispatch (request, * args, ** kwargs)

Файл "C: \ Users \ admin \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ site-packages \ django \ views \ generic \base.py "в отправке 88. обработчик возврата (запрос, * args, ** kwargs)

Файл" C: \ Users \ admin \ thesis \ blackink_website \ catalog \ views.py "в get 127. book= get_object_or_404 (книга)

Файл "C: \ Users \ admin \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ site-packages \ django \ shortcuts.py" в get_object_or_404 93. вернуть набор запросов.get (* args, ** kwargs)

Файл "C: \ Users \ admin \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ site-packages \ django \ db \ models \ query.py "в get 403. (self.model._meta.object_name, num)

Тип исключения: MultipleObjectsReturned в / premium / 1 / Значение исключения: get () вернул более одной книги - вернул 2!

Я обновлю сообщение, если информации недостаточно.Заранее спасибо.

ОБНОВЛЕНИЕ

вот мои модели.py

class Book(models.Model):


title = models.CharField(max_length=200) #i deleted some info to make it shorter

allowedMembership = models.ManyToManyField(Membership, blank=True)


def get_absolute_url(self):
    return reverse('book-detail',  args=[str(self.id)])

def __str__(self):
    return self.title

@property
def pages(self):
    return self.page_set.all()



class Page(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE, null=True)
file = models.FileField(upload_to='book_content', validators=[pdf_file_extension], help_text="PDF File Only")
timestamp = models.DateTimeField(default=timezone.now)


def __str__(self):
    return self.book.title

def get_absolute_url(self):
    return reverse('page-detail',   args=[str(self.id)])

page_detail.html

{% if user_membership and user_membership.user == request.user %}
        {% for content in book.pages %}
            <a href="{{ content.get_absolute_url }}" class="site-btn">Read</a>
        {% endfor %}
        {% else %}
        <button class="site-btn" disabled="disabled">VIP</button>
        {% endif %}

Ответы [ 2 ]

1 голос
/ 18 марта 2019

Исключение MultipleObjectsReturned вызывается запросом, если ожидается только один объект, но возвращается несколько объектов. Базовая версия этого исключения предоставляется в django.core.exceptions ; каждый класс модели содержит подклассную версию, которая может использоваться для идентификации конкретного типа объекта, который возвратил несколько объектов.

Я предполагаю, что вы используете последнюю версию Django. См. Соответствующую документацию, основанную на вашей собственной версии, перейдя с самого низа на официальный сайт.

Следующие ссылки будут лучшими для вас.

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

Настройте ваш URL на основе https://docs.djangoproject.com/en/2.1/topics/class-based-..., чтобы вы могли передать page_id, и ваш шаблон URL должен выглядеть примерно так: path('pages/<int:page_id>', PageDetailView.as_view()) или re_path("^pages/(?<page_id>\d+)$", PageDetailView. as_view()).

Будьте осторожны при использовании path () , re_path () , url () , поскольку они имеют свой собственный стиль + преимущество.

Обновление:

Изучив отношения между Book (родительская модель) и Page (дочерняя модель), я изменил urlpattern с path('pages/<int:page_id>/books/<int:book' на path('pages/<page_id>, и для идентификации страницы достаточно идентификатора страницы, поскольку ForeignKey Отношения между обеими моделями.

Поскольку вы видите PageDetailView , хорошо передавать только идентификатор страницы для лучшего дизайна, как предлагают другие (вы можете передавать несколько параметров URL-адресов слишком в зависимости от требований, но здесь нам это не нужно).

from django.http import Http404

class PageDetailView(LoginRequiredMixin, generic.View):

    def get(self, request, *args, **kwargs):
        try:
            # page = get_object_or_404(Page)
            page_id = self.kwargs["page_id"]
            page = Page.objects.get(pk=page_id) 

            # book = get_object_or_404(Book)
            book_id = page.book.pk
            book = Book.objects.get(pk=book_id)

            # user_membership = get_object_or_404(Customer, user=request.user)
            user_membership = Customer.objects.get(user=request.user)

            user_membership_type = user_membership.membership.membership_type
            user_allowed = book.allowedMembership.all()
            context = {'object': None}
            if user_allowed.filter(membership_type=user_membership_type).exists():
                context = {'object': page}
            return render(request, "catalog/page_detail.html", context)
        except Book.DoesNotExist:
            raise Http404("Book with id {0} does not exist".format(book_id))
        except Page.DoesNotExist:
            raise Http404("Page with id {0} does not exist".format(page_id))
        except Customer.DoesNotExist:
            raise Http404("Cutomer does not exist")
        except Exception as e: 
            raise Exception(str(e)) 
0 голосов
/ 18 марта 2019

Причина, по которой вы получаете эту ошибку, заключается в том, что вы используете get_object_or_404 для получения одной книги, но проблема в том, что ваш запрос возвращает несколько книг. Это обычно происходит, когда нет уникального ограничения на поле, которое вы используете для поиска книги (т.е. получение объекта по title «Книга джунглей» возвращает две книги с одинаковым названием).

Чтобы исправить это, получите объект, используя поле, которое гарантированно будет уникальным, например id . Например:

urls.py

path('page-details/<str:book_id>/<str:page_id>/', PageDetailView.as_view(), name='page_details'),

views.py

class PageDetailView(LoginRequiredMixin, generic.View):
    def get(self, request, *args, **kwargs):
        book = get_object_or_404(id=kwargs['book_id'])
        page = get_object_or_404(id=kwargs['page_id'])
        [...]
...