Django中如何通过主键自动关联拆分的患者模型?
Django患者存储系统自动关联拆分模型解决方案
一、模型关联基础配置
首先确保Hasta、HastaProfil、HastaAliskanlik三个模型通过一对一关联绑定,示例代码如下:
# models.py from django.db import models class Hasta(models.Model): # 基础患者信息 ad = models.CharField(max_length=100, verbose_name="姓名") soyad = models.CharField(max_length=100, verbose_name="姓氏") telefon = models.CharField(max_length=20, verbose_name="电话") # 其他基础字段... class HastaProfil(models.Model): hasta = models.OneToOneField( Hasta, on_delete=models.CASCADE, related_name="profil", verbose_name="关联患者" ) # 档案类字段 boy = models.FloatField(verbose_name="身高") kilo = models.FloatField(verbose_name="体重") # 其他300个拆分字段... class HastaAliskanlik(models.Model): hasta = models.OneToOneField( Hasta, on_delete=models.CASCADE, related_name="aliskanlik", verbose_name="关联患者" ) # 习惯类字段 sigara_kullanimi = models.BooleanField(verbose_name="吸烟", default=False) alkol_kullanimi = models.BooleanField(verbose_name="饮酒", default=False) # 其他拆分字段...
二、Admin面板自动关联实现
方法1:内联模型(Inline)同步编辑
将子模型嵌入Hasta的Admin页面,创建/编辑患者时可直接填写关联模型数据,自动完成绑定:
# admin.py from django.contrib import admin from .models import Hasta, HastaProfil, HastaAliskanlik class HastaProfilInline(admin.StackedInline): model = HastaProfil can_delete = False # 禁止单独删除档案,需随患者删除 verbose_name_plural = "患者档案" # 如果字段太多,可设置fieldsets拆分显示 class HastaAliskanlikInline(admin.StackedInline): model = HastaAliskanlik can_delete = False verbose_name_plural = "患者习惯" @admin.register(Hasta) class HastaAdmin(admin.ModelAdmin): inlines = [HastaProfilInline, HastaAliskanlikInline] list_display = ("ad", "soyad", "telefon") # 列表显示字段
配置后,在Admin中创建Hasta时,下方会直接显示HastaProfil和HastaAliskanlik的表单,提交后自动创建关联记录,无需手动选择。
方法2:自动创建关联子模型
如果需要单独管理子模型,可在Hasta的save方法中自动生成关联记录:
# models.py - Hasta类中添加 def save(self, *args, **kwargs): is_new = not self.pk # 判断是否为新创建的患者 super().save(*args, **kwargs) if is_new: # 自动创建关联的档案和习惯记录 HastaProfil.objects.create(hasta=self) HastaAliskanlik.objects.create(hasta=self)
这样新增患者后,对应的HastaProfil和HastaAliskanlik会自动生成,在Admin中编辑子模型时,关联字段会默认选中对应的患者。
三、批量添加患者处理
使用bulk_create批量导入患者时,需手动批量创建关联子模型(因为bulk_create不会触发模型的save方法):
# 批量创建患者 hasta_list = [ Hasta(ad="Ahmet", soyad="Yılmaz", telefon="05551234567"), Hasta(ad="Ayşe", soyad="Kaya", telefon="05559876543"), # 更多患者数据... ] Hasta.objects.bulk_create(hasta_list) # 批量创建关联档案 profil_list = [HastaProfil(hasta=hasta) for hasta in hasta_list] HastaProfil.objects.bulk_create(profil_list) # 批量创建关联习惯 aliskanlik_list = [HastaAliskanlik(hasta=hasta) for hasta in hasta_list] HastaAliskanlik.objects.bulk_create(aliskanlik_list)
四、患者自助注册实现
整合式表单(单页提交)
创建整合三个模型字段的表单,在视图中统一处理保存:
# forms.py from django import forms from .models import Hasta, HastaProfil, HastaAliskanlik class HastaKayitForm(forms.Form): # 患者基础字段 ad = forms.CharField(max_length=100, label="姓名") soyad = forms.CharField(max_length=100, label="姓氏") telefon = forms.CharField(max_length=20, label="电话") # 档案字段 boy = forms.FloatField(label="身高") kilo = forms.FloatField(label="体重") # 习惯字段 sigara_kullanimi = forms.BooleanField(label="吸烟", required=False) alkol_kullanimi = forms.BooleanField(label="饮酒", required=False) # 其他300个字段按需添加... def save(self): # 先保存基础患者信息 hasta = Hasta.objects.create( ad=self.cleaned_data["ad"], soyad=self.cleaned_data["soyad"], telefon=self.cleaned_data["telefon"] ) # 保存档案 HastaProfil.objects.create( hasta=hasta, boy=self.cleaned_data["boy"], kilo=self.cleaned_data["kilo"] ) # 保存习惯 HastaAliskanlik.objects.create( hasta=hasta, sigara_kullanimi=self.cleaned_data["sigara_kullanimi"], alkol_kullanimi=self.cleaned_data["alkol_kullanimi"] ) return hasta
# views.py from django.shortcuts import render, redirect from .forms import HastaKayitForm def hasta_kayit(request): if request.method == "POST": form = HastaKayitForm(request.POST) if form.is_valid(): hasta = form.save() return redirect("hasta_detay", pk=hasta.pk) # 跳转至患者详情页 else: form = HastaKayitForm() return render(request, "hasta_kayit.html", {"form": form})
分步骤表单(优化长表单体验)
如果300个字段过于冗长,可采用分步骤提交:
- 第一步提交患者基础信息,将数据存入session
- 第二步提交档案信息,更新session
- 第三步提交习惯信息,从session取出所有数据,批量保存三个模型
示例视图逻辑:
# views.py def kayit_adim1(request): if request.method == "POST": # 处理基础字段,存入session request.session["hasta_bilgi"] = { "ad": request.POST.get("ad"), "soyad": request.POST.get("soyad"), "telefon": request.POST.get("telefon") } return redirect("kayit_adim2") return render(request, "kayit_adim1.html") def kayit_adim2(request): if request.method == "POST": request.session["profil_bilgi"] = { "boy": request.POST.get("boy"), "kilo": request.POST.get("kilo") } return redirect("kayit_adim3") return render(request, "kayit_adim2.html") def kayit_adim3(request): if request.method == "POST": # 取出session数据,保存所有模型 hasta_bilgi = request.session.get("hasta_bilgi") profil_bilgi = request.session.get("profil_bilgi") aliskanlik_bilgi = { "sigara_kullanimi": request.POST.get("sigara_kullanimi") == "on", "alkol_kullanimi": request.POST.get("alkol_kullanimi") == "on" } hasta = Hasta.objects.create(**hasta_bilgi) HastaProfil.objects.create(hasta=hasta, **profil_bilgi) HastaAliskanlik.objects.create(hasta=hasta, **aliskanlik_bilgi) # 清空session del request.session["hasta_bilgi"] del request.session["profil_bilgi"] return redirect("hasta_detay", pk=hasta.pk) return render(request, "kayit_adim3.html")
内容的提问来源于stack exchange,提问作者Prusa
相关产品推荐
相关产品推荐

