Как мне отфильтровать определенные элементы в поле модели по идентификатору другой модели?

#python #django

#python #django

Вопрос:

Это довольно странный вопрос

 class Post(models.Model):
    name = models.CharField(max_length=200)

class PostKey(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    name = models.CharField(max_length=200)

    def __str__(self):
        return self.post.name   " | "   self.name
 

Я пытаюсь использовать детальное представление таким образом, чтобы оно отображало детали Post модели, а также показывало список PostKey (не мог придумать никакого другого имени), который имеет тот же идентификатор, post.id что и . Я создал отношение » один ко многим » с Post использованием модели ForeignKey .

Вот мое мнение:

 from django.shortcuts import render 
from django.views.generic import TemplateView, DetailView
from .models import Post, PostKey

class TestView(TemplateView):
    template_name = "test.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["posts"] = Post.objects.all()
        return context

class PostDetailView(DetailView, Post):
    template_name = "test2.html"
    model = Post
    
    def get_context_data(self, **kwargs ):
        context = super().get_context_data( **kwargs)
        
        context['details'] = PostKey.objects.filter(id= Post.id)
        return context
 

но когда я запускаю этот код, он показывает мне что-то вроде этого:

 TypeError at /post/2
Field 'id' expected a number but got <django.db.models.query_utils.DeferredAttribute object at 0x03F88478>.

 

Я пытался добавить int(Post.id) , но это все равно не работает.

Вот шаблон, который визуализируется для приведенного выше представления.

 {% for detail in details %}   
      {{detail.name}}
{% endfor %}
 

Любая помощь будет оценена

Комментарии:

1. @WillemVanOnsem помогите мне с этим

Ответ №1:

Вы фильтруете с помощью:

 def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['details'] = PostKey.objects.filter(post=self.object)
    return context 

или с помощью:

 def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['details'] = self.object.postkey_set.all()
    return context 

Комментарии:

1. что означает self.object, я этого не понимаю

2. извините, если я вас расстраиваю, ребята, я всего лишь начинающий разработчик, и меня смущает так много вещей

Ответ №2:

Код, который вы написали

 context['details'] = PostKey.objects.filter(id= Post.id)
 

не работает, потому Post что это класс модели, а не экземпляр модели, что означает, что Post.id это определение поля модели для класса, а не значение Post экземпляра, который вы ищете; экземпляр в DetailView находится внутри self.object .

Кроме того, вы, вероятно, захотите выполнить поиск во всех PostKey экземплярах, которые self.object являются родительскими, а не в тех, которые имеют тот же идентификатор, что и родительский; вам нужно фильтровать с помощью поля PostKey.post (которое является внешним ключом для родительского Post ).


Вероятно, вам нужно использовать Post экземпляр (in self.object ) для фильтрации всех PostKey объектов, которые self.object являются их родительскими.

 class PostDetailView(DetailView):
    template_name = "test2.html"
    model = Post
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        context['details'] = PostKey.objects.filter(post=self.object)

        # or also the way @WillemVanOnsem suggested in his answer
        # context['details'] = self.object.postkey_set.all()

        return context
 

И код шаблона, который вы показали, кажется прекрасным:

 {% for det in details %}   
    {{ det.name }}
    {{ det }}          <!-- this will use method PostKey.__str__() -->
{% endfor %}
 

Кроме того, почему ваш класс наследуется от Post (у вас есть class PostDetailView(DetailView, Post): )?
Это не кажется правильным, DetailView в этом случае оно должно просто наследоваться.

Комментарии:

1. ваш ответ имеет смысл, и я собираюсь попробовать его сейчас, когда у меня ничего не получалось, я просто сделал PostDetailView inherit from Post, чтобы попробовать другой подход

2. можете ли вы также помочь мне показать это в шаблоне

3. @Flamiooo Ваш код шаблона выглядит нормально; повторение details и отображение каждой детали должны работать с кодом шаблона, который вы показали.

4. это работает, и я, наконец, могу работать над реальным проектом