我如何在Django上创建过滤器功能来支持多个模型?

njthzxwz  于 2023-07-01  发布在  Go
关注(0)|答案(1)|浏览(80)

我有两个模型:

from django.db import models

class Profil(models.Model):
    nik     = models.IntegerField()
    nama    = models.CharField(max_length=40)
    tgl     = models.DateField()
    kelamin = models.CharField(max_length=10)
    namaibu = models.CharField(max_length=40)
    nikibu  = models.IntegerField()
    dusun  = models.CharField(max_length=30, default='Sumberejo')

    def __str__(self):
        return f"{self.nik}, {self.nama}, {self.namaibu}"
    
class Posyandu(models.Model):
    bulan  = models.CharField(max_length=20, default='Januari')
    nik = models.ForeignKey(Profil, on_delete=models.CASCADE)
    tb  = models.IntegerField()
    bb  = models.IntegerField()
    ll  = models.IntegerField()
    lk  = models.IntegerField()
    ket = models.CharField(max_length=20,)

    def __str__(self):
        return f"{self.nik.nama}, {self.bulan}, {self.tb}, {self.bb}"

并将它们显示为带有此html的表格

<table>
        <thead>
            <tr>
                <th>NIK</th>
                <th>Nama</th>
                <th>Tanggal Lahir</th>
                <th>Kelamin</th>
                <th>Nama Ibu</th>
                <th>Bulan</th>
                <th>TB</th>
                <th>BB</th>
                <th>LL</th>
                <th>LK</th>
                <th>Keterangan</th>
            </tr>
        </thead>
        <tbody>
            {% for profil in profils %}
            {% for posyandu in profil.posyandu_set.all %}
            <tr>
                <td>{{ profil.nik }}</td>
                <td>{{ profil.nama }}</td>
                <td>{{ profil.tgl }}</td>
                <td>{{ profil.kelamin }}</td>
                <td>{{ profil.namaibu }}</td>
                <td>{{ posyandu.bulan }}</td>
                <td>{{ posyandu.tb }}</td>
                <td>{{ posyandu.bb }}</td>
                <td>{{ posyandu.ll }}</td>
                <td>{{ posyandu.lk }}</td>
                <td>{{ posyandu.ket }}</td>
            </tr>
            {% endfor %}
            {% empty %}
            <tr>
                <td colspan="11">No data available</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>

除此之外,我尝试构建一个过滤器功能,能够根据月份字段(Posyandu上的bulan字段)过滤表上显示的内容,并使用此views.py this views.py

def riwayat(response):
    profils = Profil.objects.prefetch_related('posyandu_set')
    if response.method == 'POST':
        forms = BulanForm(response.POST)
        if forms.is_valid():
            bulan = forms.cleaned_data['bulan']
            profils = profils.filter(posyandu__bulan=bulan)
        
    else:
        forms = BulanForm()
    return render(response, 'all.html', {'profils': profils, 'forms' : forms})

而这种形式

class BulanForm(forms.Form):
    pilihanbulan = [
    ('Januari', 'Januari'),
    ('Februari', 'Februari'),
    ('Maret', 'Maret'),
    ('April', 'April'),
    ('Mei', 'Mei'),
    ('Juni', 'Juni'),
    ('Juli', 'Juli'),
    ('Agustus', 'Agustus'),
    ('September', 'September'),
    ('Oktober', 'Oktober'),
    ('November', 'November'),
    ('Desember', 'Desember'),
]

    bulan = forms.ChoiceField(
        required = True,
        widget = forms.Select,
        choices = pilihanbulan,
        label = 'Posyandu Bulan'

    )

过滤器工作,但不正确,我的意思是它确实过滤并显示了基于用户选择的月份的数据,但也显示了同一个配置文件所拥有的其他Posyandu数据。例如,列奥纳多在1月和6月有Posyandu数据。当我过滤数据以显示在Januari上时,不知何故列奥纳多在June的数据也被显示。也许这个解释仍然缺乏,请参考这个截图以获得更多上下文[https://i.imgur.com/XbvSYMz.png]
我的结论是,程序正在显示Profil所拥有的包含所选月份的所有Posyandu对象。因此,如果人员A在1月、3月和9月有Posyandu数据,并且用户选择基于1月进行过滤,则程序将显示所有人员A的Posyandu数据,因为人员A在1月有Posyandu的数据。
我希望我的筛选器只显示选定的月份。我怎么做到的
如果我的问题令人困惑,我很抱歉,因为英语不是我的母语。感谢您阅读这个问题。

68de4m5k

68de4m5k1#

您还需要筛选预取对象:

from django.db.models import Prefetch

def riwayat(response):
    profils = Profil.objects.prefetch_related('posyandu_set')
    if response.method == 'POST':
        forms = BulanForm(response.POST)
        if forms.is_valid():
            bulan = forms.cleaned_data['bulan']
            profils = Profil.objects.prefetch_related(
                Prefetch('posyandu_set', Posyandu.objects.filter(bulan=bulan))
            ).filter(posyandu__bulan=bulan)

    else:
        forms = BulanForm()
    return render(response, 'all.html', {'profils': profils, 'forms': forms})

因此,这不仅会过滤Profil对象,使得它只接受具有正确bulan的相关PosyanduProfil s,而且还会过滤相关Posyandu对象的集合,因此只有这些对象最终会出现在.posyandu_set s上。Profil的数据。

相关问题