如何在 Django 中获取特定的查询集

How to get a specific queryset in Django

我正在构建医院管理应用程序,目前正在构建护士的网页。在该网页中,我希望显示以下内容:所有受雇护士的列表、他们的轮班列表以及他们工作的部门。

我正在尝试显示部门部分,但我一直收到错误消息“要解压的值太多(预期为 2)”。

我该怎么做才能让护士部显示?

Models.py

from django.db import models

# Create your models here.

#Work Related aka Department and Work Shift

class Department(models.Model):
    name = models.CharField(max_length=200, null=True, blank=True)

    def __str__(self):
        return self.name

class WorkShift(models.Model):
    name = models.CharField(max_length=200, null=True, blank=True)
    start_datetime = models.DateTimeField(null=True, blank=True)
    end_datetime = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return self.name 

#Personel Related aka Employees and Patients

class Doctor(models.Model):
    name = models.CharField(max_length=200, null=True, blank=True)
    email = models.CharField(max_length=200, null=True)
    phone = models.CharField(max_length=200, null=True)
    department = models.ForeignKey(Department, null=True, blank=True, on_delete=models.CASCADE)
    work_shift = models.OneToOneField(WorkShift, blank=True, null=True, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class Nurse(models.Model):
    name = models.CharField(max_length=200, null=True)
    email = models.CharField(max_length=200, null=True)
    phone = models.CharField(max_length=200, null=True)
    sector = models.ForeignKey(Department, null=True, blank=True, on_delete=models.CASCADE)
    reports_to = models.ForeignKey(Doctor, blank=True, null=True, on_delete=models.CASCADE)
    work_shift = models.OneToOneField(WorkShift, default="", blank=True, null=True, on_delete=models.CASCADE)
    
    def __str__(self):
         return self.name

class Patient(models.Model):
    STATUS = (
        ('Sick', 'Sick'),
        ('Healing', 'Healing'),
        ('Cured', 'Cured'),
        ('Deceased', 'Deceased'),
    )

    name = models.CharField(max_length=200, null=True, blank=True)
    description = models.TextField(blank=True, null=True)
    status = models.CharField(max_length=200, null=True, blank=True, choices=STATUS)
    department = models.ForeignKey(Department, default="", null=True, blank=True, on_delete=models.CASCADE)
    care = models.ForeignKey(Nurse, default="", blank=True, null=True, on_delete=models.CASCADE)
    date_created = models.DateTimeField(auto_now_add=True, blank=True, null=True)

    def __str__(self):
        return self.name

from django.shortcuts import render, redirect

Views.py

# Create your views here.
from django.shortcuts import render
from .models import Doctor, Nurse, Patient, Department, WorkShift
from django.http import HttpResponse
from .forms import DoctorForm, NurseForm, PatientForm

# Create your views here.
def index(request):
    patient = Patient.objects.all()
    nurse = Nurse.objects.all()
    doctor = Doctor.objects.all()
    department = Department.objects.all()

    total_patient = patient.count()
    sick = patient.filter(status='Sick').count()
    healing = patient.filter(status='Healing').count()
    cured = patient.filter(status='Cured').count()

    total_nurse = nurse.count()

    # if request.method == 'POST':
    #     form = 

    context = {
        'patient':patient, 'nurse':nurse,
        'doctor':doctor, 'total_patient':total_patient,
        'sick':sick, 'healing':healing, 'cured':cured,
        'total_nurse':total_nurse,
        'department':department
    }

    return render(request, 'lifesaver/index.html', context)

#All Patient Related

def patient(request):
    patient = Patient.objects.all()

    context = {'patient':patient}
    return render(request, 'lifesaver/patient.html', context)

def patient_add(request):

    patient = Patient.objects.all()
    form = PatientForm()

    if request.method == 'POST':
        form = PatientForm(request.POST)
        if form.is_valid():
            print("Patient Form is Valid")
            form.save()
        else:
            print("Patient Form is Invalid")
            print(form.errors)
        return redirect('patient')

    context = {'form':form,}
    return render(request, 'lifesaver/patient_add.html', context)

def patient_update(request, pk):

    patient = Patient.objects.get(id=pk)
    form = PatientForm(instance=patient)

    if request.method == 'POST':
        form = PatientForm(request.POST, instance=patient)
        if form.is_valid():
            print('Update completed')
            form.save()
            return redirect('patient')
        else:
            print('Update not completed')
            print(form.errors)
            
    context = {'form':form}

    return render(request, 'lifesaver/patient_update.html', context)

#All Doctor Related

def doctor(request):

    doctor = Doctor.object.all()

    context = {}
    return render(request, 'lifesaver/doctor.html', context)

def doctor_add(request):
    
    doctor = Doctor.object.all()
    form = DoctorForm()

    context = {'doctor':doctor, 'form':form}
    return render(request, 'lifesaver/doctor')

def doctor_update(request):

    doctor = Doctor.object.all()
    form = DoctorForm()

    context = {'doctor':doctor, 'form':form}

# Nurse Related

def nurse(request):
    nurse = Nurse.objects.all()
    workshift = WorkShift.objects.all()
    department = Nurse.objects.get('sector')

    context = {'nurse':nurse, 'workshift':workshift, 'department':department}
    return render(request, 'lifesaver/nurse.html', context)
    

def nurse_add(request):
    nurse = Nurse.objects.all()
    form = NurseForm()

    if request.method == 'POST':
        form = NurseForm(request.POST)
        if form.is_valid():
            print("Nurse Form is Valid")
            form.save()
        else:
            print("Nurse Form is Invalid")
            print(form.errors)
        return redirect('nurse')

    context = {'form':form,}
    return render(request, 'lifesaver/nurse_add.html', context)

def nurse_update(request):
    nurse = Nurse.objects.all()
    form = NurseForm()

    context = {}
    return render(request, 'lifesaver/nurse_update.html', context)

#Work Related

def department(request):
    department = Department.objects.all()

    context = {'department':department}
    return render(request, 'lifesaver/department.html', context)

Forms.py

from django import forms
from django.forms import ModelForm
from .models import Doctor, Nurse, Patient, Department, WorkShift
from django.contrib.auth.forms import UserCreationForm

class DoctorForm(forms.ModelForm):
    name = forms.CharField(widget = forms.TextInput(attrs = 
    {

            'placeholder': 'Add a New Doctor',
            'class': 'form-control'
    }
    ))

    department = forms.ModelChoiceField(queryset=Department.objects.all(), widget=forms.Select(attrs=
    {
            'class': 'selectpicker',
            'placeholder': 'Department', 
    }
    )) 

    class Meta:
        model = Doctor
        fields = ['name', 'department']

class NurseForm(forms.ModelForm):
    name = forms.CharField(widget = forms.TextInput(attrs = 
    {

            'placeholder': 'Add a New Nurse',
            'class': 'form-control'
    }
    ))

    class Meta:
        model = Nurse
        fields = ['name']

class PatientForm(ModelForm):
    name = forms.CharField(widget = forms.TextInput(attrs = 
    {

            'placeholder': 'Add a New Nurse',
            'class': 'form-control'
    }
    ))

    description = forms.CharField(widget = forms.TextInput(attrs =
    {
            'placeholder': "Describe the patient's symptoms",
            'class': 'form-control'
    }
    ))

    department = forms.ModelChoiceField(queryset=Department.objects.all(), widget=forms.Select(attrs=
    {
            'class': 'selectpicker',
            'placeholder': 'Select Department', 
    }
    )) 

    class Meta:
        model = Patient
        fields = ['name', 'description', 'department', 'care', 'status']

#Work Related

class WorkShiftForm(ModelForm):
        class Meta:
                model = WorkShift
                fields = '__all__'

Nurse.html

{% extends 'lifesaver/main.html' %}

{% block content %}

{% for nurse in nurse %}
    {{nurse.name}}
    {{nurse.report_to}}
    {{nurse.care}}
    {{nurse.work_shift}}
    {{department}}
{% endfor %}


{% endblock %}

您需要传递一个字段和一个值,例如

  Nurse.objects.get('sector' = 'dentistry')

或者如果您想显示特定的护士部门,您可以在模板中使用它:

{{nurse.department.name}}

在 models.py 中,Nurse 对象具有字段 'sector',它是部门记录的外键。所以部分问题是您试图在模板中输出错误的字段名称,因为 Nurse 模型上没有定义实际的 department 字段。

尝试对 views.py 进行这些编辑: nurses = Nurse.objects.all() 然后在您的上下文中:context = {..., 'nurses': nurses, ...}

然后在nurse.html:

{% for nurse in nurses: %}
   ...
   {{ nurse.sector.name }}
{% endfor %}

至少应该让您的护士对象呈现在模板中。但是,当 FK 在 Nurse 模型中使用 null=True 定义时,您在调用 nurse.sector 时可能会遇到问题。因此,更好的做法是在 Nurse 模型中定义一个访问器方法,以在调用 name 之前检查 sector 是否存在,即:

# in Nurse model
def department_name(self):
    if self.sector_id:
        return self.sector.name
    else:
        return '' # or some other default

然后您可以再次编辑 nurse.html,将我上面的代码替换为:

{% for nurse in nurses: %}
   ...
   {{ nurse.department_name }}
{% endfor %}

这只是您如何处理这个问题的冰山一角,但它有望回答您的问题并防止在您进行这些编辑后出现常见错误。

您可能还想查看 Django QuerySet API's select_related() and prefetch_related() methods to avoid N+1 query issues that are possible in your current code. See here and here 了解更多背景信息。

因此,例如,为了避免 N+1,而不是调用 nurses = Nurse.objects.all(),而是调用 nurses = Nurse.objects.select_related('sector').all()。这将加入 FK 上的 Department 模型。 This answer 以上 N+1 个问题之一有更多详细信息。