Фильтрация набора запросов по значению внешнего ключа в ListView - PullRequest
1 голос
/ 16 июня 2019

Я пытаюсь отфильтровать набор запросов, установив значение внешнего ключа, равное URL-слагу.

models.py

class Parent(models.Model):

    parent_name = models.CharField(unique=True, max_length=40)

    parent_slug = models.SlugField(unique=True)


class Child(models.Model):

    child_name = models.CharField(unique=True, max_length=40, default=1)

    child_slug = models.SlugField(unique=True, default=1)

    parent_slug = models.ForeignKey(Parent, on_delete=models.CASCADE,default = 1)

urls.py

from .views import ChildListView

urlpatterns = [
    ...
    path('<parent_slug>/children/', ChildListView.as_view(), name='child_list'),
    ...
]

views.py

class ChildListView(ListView):

    template_name = 'child_list.html'

    context_object_name = 'child'

    def get_queryset(self):

        slug_param = self.kwargs['parent_slug']

        qs = Child.objects.filter(parent_slug = slug_param)

        return qs   

Это результат ошибки:

Значение исключения:
Невозможно разрешить ключевое слово 'parent' в поле.

1 Ответ

1 голос
/ 16 июня 2019

Вам необходимо отфильтровать по parent_slug объекта Parent (который обозначен как parent_slug), поэтому вы фильтруете с помощью:

class ChildListView(ListView):
    template_name = 'child_list.html'
    context_object_name = 'child'

    def get_queryset(self):
        return Child.objects.filter(<b>parent_slug__parent_slug=self.kwargs['parent_slug']</b>)

При этом номенклатура в моделировании немного нечетная . Обычно поля не имеют префикс с именем модели, а ForeignKey относится к объекту модели, к которому относится поле, а не к его слагу. Более того, вероятно, не имеет смысла устанавливать default=1 для ForeignKey, так как это может позже относиться к другому объекту, чем тот, который вы держите. Наконец, установка default=1 на SlugField определенно не имеет особого смысла.

Вероятно, лучший способ определить ваши модели:

class Parent(models.Model):
    <b>name</b> = models.CharField(unique=True, max_length=40)
    <b>slug</b> = models.SlugField(unique=True)

class Child(models.Model):
    <b>name</b> = models.CharField(unique=True, max_length=40)
    <b>slug</b> models.SlugField(unique=True)
    <b>parent</b> = models.ForeignKey(Parent, on_delete=models.CASCADE)

мы можем даже абстрагировать name и slug в абстрактной базовой модели (например, NameSlugModel), например:

class NameSlugModel(models.Model):
    name = models.CharField(unique=True, max_length=40)
    slug = models.SlugField(unique=True)

    class Meta:
        <b>abstract = True</b>

class Parent(<b>NameSlugModel</b>):
    pass

class Child(<b>NameSlugModel</b>):
    parent = models.ForeignKey(Parent, on_delete=models.CASCADE)

В этом случае вы фильтруете:

class ChildListView(ListView):
    template_name = 'child_list.html'
    context_object_name = 'child'

    def get_queryset(self):
        return Child.objects.filter(<b>parent__slug</b>=self.kwargs['parent_slug'])
...