【问题标题】:How to filter related model rows of a django model?如何过滤 django 模型的相关模型行?
【发布时间】:2021-09-04 00:58:58
【问题描述】:

目前正在返回所有相关对象。如果我尝试获得 PortfolioUser 的教育,我想以这种方式限制相关对象,我只得到具有值 show=True

models.py

from django.db import models
from django.db.models import Q
from django.db.models.signals import pre_save, post_save
# Create your models here.


class PortfolioUser(models.Model):

    GENDER_CHOICES = [
        ("M", "Male"),
        ("F", "Female")
    ]

    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    email = models.EmailField(max_length=254)
    phone_number = models.CharField(max_length=50)
    gender = models.CharField(choices=GENDER_CHOICES,
                              max_length=1, null=True, default='M')
    about = models.TextField(null=True, default="Lorem ipsum dolor sit amet consectetur adipisicing elit. Ad, blanditiis optio. Quia, corporis quidem. Nam aliquam officia rerum consequatur nisi ducimus nihil saepe aut excepturi, accusantium aspernatur possimus quod error!")
    is_active = models.BooleanField(default=False)

    class Meta:
        verbose_name = ("PortfolioUser")
        verbose_name_plural = ("PortfolioUsers")

    def __str__(self):
        return self.first_name+" "+self.last_name

    def get_absolute_url(self):
        return reverse("PortfolioUser_detail", kwargs={"pk": self.pk})


class Education(models.Model):
    education_name = models.CharField(max_length=254)
    institute_name = models.CharField(max_length=254)
    start_year = models.DateField(auto_now=False, auto_now_add=False)
    end_year = models.DateField(auto_now=False, auto_now_add=False)
    marks = models.CharField(max_length=50)
    show = models.BooleanField(default=True)

    portfolio_user = models.ForeignKey(
        PortfolioUser, on_delete=models.CASCADE, related_name="educations")

    class Meta:
        verbose_name = ("Education")
        verbose_name_plural = ("Educations")

    def __str__(self):
        return self.education_name+" -"+self.portfolio_user.first_name

    def get_absolute_url(self):
        return reverse("Education_detail", kwargs={"pk": self.pk})


class Project(models.Model):

    project_name = models.CharField(max_length=50)
    about = models.TextField(null=False)
    website = models.CharField(max_length=100, null=True, blank=True)
    github = models.CharField(max_length=100, null=True, blank=True)
    thumbnail = models.ImageField(upload_to="projects/thumbnails",
                                  height_field=None, width_field=None, max_length=None)
    show = models.BooleanField(default=True)

    portfolio_user = models.ForeignKey(
        PortfolioUser, on_delete=models.CASCADE, related_name="projects")

    class Meta:
        verbose_name = ("Project")
        verbose_name_plural = ("Projects")

    def __str__(self):
        return self.project_name+" -"+self.portfolio_user.first_name

    def get_absolute_url(self):
        return reverse("Project_detail", kwargs={"pk": self.pk})


def portfolio_user_active_changed_signal(sender, instance, **kwargs):
    thisObj = PortfolioUser.objects.filter(id=instance.id).first()
    if not thisObj.is_active == instance.is_active:
        # field is changed
        otherPortfolioUsers = PortfolioUser.objects.filter(~Q(id=instance.id))
        otherPortfolioUsers.update(is_active=False)


def make_default_portfolio_user_active(sender, instance, **kwargs):
    # gets at leat one active user if exists
    active_portfolio_user = PortfolioUser.objects.filter(
        is_active=True).first()
    if not active_portfolio_user:
        first_user = PortfolioUser.objects.filter(id=1)
        first_user.update(is_active=True)


pre_save.connect(portfolio_user_active_changed_signal, sender=PortfolioUser)
post_save.connect(make_default_portfolio_user_active, sender=PortfolioUser)

views.py

class PortfolioUserListView(ListView):
    model = PortfolioUser
    queryset = model.objects.filter(
        is_active=True, educations__show=True)
    template_name = "main/index2.html"
    context_object_name = "portfolio_user"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["title"] = context['portfolio_user']
        print(context)
        return context

我在教育中有两个条目(行)。这些行中只有一个具有show = False。
但是当我尝试访问portfolio_user.first.educations.all 时,它返回的对象仍然包含show=False 所在的值

我怎样才能使我的最终上下文只包含 show=true 的相关教育?

【问题讨论】:

    标签: python sql django django-models


    【解决方案1】:

    没有从 PortfolioUser 到 Education 的外键。您可以尝试的是:

    # in your class view
    def get_queryset(self):
        return Education.objects.select_related(
            "portfolio_user"
        ).filter(
            show=True, portfoliouser__is_active=True
        ).only("portfolio_user")
    

    这样,即使教育查询集返回给您,投资组合用户也会在这个单一查询中返回给您。

    【讨论】:

      【解决方案2】:

      portfolio_user.first().educations.filter(show=False)

      【讨论】:

        猜你喜欢
        • 2017-06-22
        • 1970-01-01
        • 1970-01-01
        • 2020-01-19
        • 2020-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多