【问题标题】:Django Show Unique List Of Subjects (Many To Many) In Dropdown MenuDjango 在下拉菜单中显示唯一的主题列表(多对多)
【发布时间】:2019-11-17 21:07:57
【问题描述】:

我希望能够在我的模板中生成一个带有唯一主题列表的下拉菜单。

主题填充在 admin 内部,而不是在 SUBJECT_CHOICES 中硬编码。

一门课程可以有很多科目,也可以只有一门科目。例如:

课程名称 = Django 主题 = 技术

课程名称 = Python 主题 = 技术

课程名称 = 会计 主题 = 业务

课程名称 = 电子商务 主题 = 技术、商业

CourseListView 对应 course_list.html 模板。

models.py:

class Subject(models.Model):
    SUBJECT_CHOICES = ()
    name = models.CharField(max_length=20,choices=SUBJECT_CHOICES, unique=True)

    def __str__(self):
        return self.name

class Course(models.Model):
​
    SKILL_LEVEL_CHOICES = (
        ('Beginner', 'Beginner'),
        ('Intermediate', 'Intermediate'),
        ('Advanced', 'Advanced'),
    )
​
    slug = models.SlugField()
    title = models.CharField(max_length=120)
    description = models.TextField()
    allowed_memberships = models.ManyToManyField(Membership)
    created_at = models.DateTimeField(auto_now_add=True)
    subjects = models.ManyToManyField(Subject)
    skill_level = models.CharField(max_length=20,choices=SKILL_LEVEL_CHOICES, null=True)
    visited_times = models.IntegerField(default=0)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('courses:detail', kwargs={'slug': self.slug})

    @property
    def lessons(self):
        return self.lesson_set.all().order_by('position')

views.py:

class CourseListView(ListView):
    model = Course
    def get_queryset(self):
        qs = super().get_queryset()
        title_contains_query = self.request.GET.get('title_contains')
        view_count_min = self.request.GET.get('view_count_min')
        view_count_max = self.request.GET.get('view_count_max')
        date_min = self.request.GET.get('date_min')
        date_max = self.request.GET.get('date_max')
        skill_level_query = self.request.GET.get('skill_level')
        if title_contains_query:
            qs = qs.filter(title__icontains=title_contains_query)
        if view_count_min:
            qs = qs.filter(visited_times__gte=view_count_min)
        if view_count_max:
            qs = qs.filter(visited_times__lte=view_count_max)
        if date_min:
            qs = qs.filter(created_at__gte=date_min)
        if date_max:
            qs = qs.filter(created_at__lte=date_max)
        if skill_level_query:
            qs = qs.filter(skill_level=skill_level_query)
        return qs

期望的输出:

我尝试在我的模板中编写一个 for 循环,该循环确实成功返回了主题,但它们不是唯一的或只显示一次。

{% for item in object_list %}
<h2>{{ item.subjects.all}}</h2>
<ul>
    {% for sub in item.subjects.all %}
    <li><a href="#" id="">{{ sub.name }}</a></li>
    {% endfor %}
</ul>
{% endfor %}

​ 结果: ​

<QuerySet [<Subject: Business>]>
Business
<QuerySet [<Subject: Technology>]>
Technology
<QuerySet [<Subject: Technology>]>
Technology
<QuerySet [<Subject: Business>]>
Business

我更喜欢使用产生独特结果的 for 循环来完成,但也许可以使用 django-select2 或使用带有模型选择或多模型选择的表单来完成?有人可以为循环或其中一种方法提供一些代码吗?

我将不胜感激。

【问题讨论】:

  • 欢迎来到 Stack Overflow _ 参考您的声明“我尝试在我的模板中编写一个 for 循环”;请在您尝试过的帖子中添加任何代码。即使它没有产生预期的结果,它也可能是其他贡献者帮助您的一个很好的起点。请阅读关于创建最小可重复代码示例的常见问题解答 >>> stackoverflow.com/help/minimal-reproducible-example

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


【解决方案1】:

我在这里看到了两种解决方案:

第一个如果只是简单地获取 Subject 模型中输入的所有值,但您不能使用视图中使用的所有过滤器,只能使用关于标题的过滤器。

为此,只需使用:

title_contains_query = self.request.GET.get('title_contains')
if title_contains_query:
    subjects = [title for title in Subject.objects.filter(title__icontains=title_contains_query)]

另一个选项是在您的 QuerySet 上使用 distinct() 方法,该方法过滤并删除其中的重复条目。像这样使用它:qs = qs.distinct()

希望对你有帮助!

【讨论】:

  • 我会把你的代码放在哪里?在models.py 的Subject 类中还是在CourseListView 类中?使用您的代码后,for 循环将如何变化?您可以使用 dpaste 或其他方法帮助我使用第一种方法或不同的方法将您的答案与我的代码结合起来吗?
  • 两种解决方案都将放在CourseListView 类中,在get_queryset 方法中,但我不能确定,因为我认为你没有将所有代码都放在类中。您能否添加剩下的内容,或者至少添加 get 和/或 post(哪个有用)?
猜你喜欢
  • 1970-01-01
  • 2021-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-13
相关资源
最近更新 更多