Django开发中医针灸经络图系统实战

发布于:2025-08-04 ⋅ 阅读:(11) ⋅ 点赞:(0)

基于 Django Web 开发中医针灸管理经络图系统的实用

以下是基于 Django Web 开发中医针灸管理经络图系统的实用示例,涵盖模型设计、视图逻辑、模板渲染等关键环节,提供典型代码片段:

模型设计(Meridian 和 Acupoint)

# models.py
class Meridian(models.Model):
    name = models.CharField(max_length=50, verbose_name="经络名称")
    abbreviation = models.CharField(max_length=10, verbose_name="缩写")
    description = models.TextField(verbose_name="经络描述")
    image = models.ImageField(upload_to='meridians/', null=True)

    def __str__(self):
        return self.name

class Acupoint(models.Model):
    name = models.CharField(max_length=50, verbose_name="穴位名称")
    code = models.CharField(max_length=10, verbose_name="代号")
    meridian = models.ForeignKey(Meridian, on_delete=models.CASCADE)
    location = models.TextField(verbose_name="定位")
    function = models.TextField(verbose_name="功能")
    needling_method = models.TextField(verbose_name="针刺方法")

    class Meta:
        ordering = ['meridian', 'code']

数据导入示例(JSON 批量导入)

# management/commands/import_meridians.py
from django.core.management.base import BaseCommand
import json

class Command(BaseCommand):
    def handle(self, *args, **options):
        with open('meridians.json', encoding='utf-8') as f:
            data = json.load(f)
            for item in data['meridians']:
                Meridian.objects.create(
                    name=item['name'],
                    abbreviation=item['abbreviation'],
                    description=item['description']
                )

视图逻辑(经络列表+搜索)

# views.py
def meridian_list(request):
    query = request.GET.get('q')
    meridians = Meridian.objects.all()
    
    if query:
        meridians = meridians.filter(
            models.Q(name__icontains=query) |
            models.Q(abbreviation__icontains=query)
        )
    
    return render(request, 'tcm/meridian_list.html', {'meridians': meridians})

模板渲染(经络卡片展示)

<!-- templates/tcm/meridian_list.html -->
{% for meridian in meridians %}
<div class="card">
  <img src="{
  
  { meridian.image.url }}" class="card-img-top">
  <div class="card-body">
    <h5>{
  
  { meridian.name }} ({
  
  { meridian.abbreviation }})</h5>
    <p>{
  
  { meridian.description|truncatechars:100 }}</p>
    <a href="{% url 'meridian_detail' meridian.id %}" class="btn btn-primary">
      查看详情
    </a>
  </div>
</div>
{% endfor %}

经络详情页(带穴位列表)

# views.py
def meridian_detail(request, pk):
    meridian = get_object_or_404(Meridian, pk=pk)
    acupoints = Acupoint.objects.filter(meridian=meridian)
    return render(request, 'tcm/meridian_detail.html', {
        'meridian': meridian,
        'acupoints': acupoints
    })

交互式经络图(SVG+JavaScript)

<!-- templates/tcm/meridian_map.html -->
<svg id="meridian-map" viewBox="0 0 800 600">
  {% for meridian in meridians %}
  <path 
    class="meridian-path" 
    d="{
  
  { meridian.svg_path }}"
    data-meridian-id="{
  
  { meridian.id }}"
    fill="none" 
    stroke="#d35400" 
    stroke-width="3"
  />
  {% endfor %}
</svg>

<script>
document.querySelectorAll('.meridian-path').forEach(path => {
  path.addEventListener('click', () => {
    window.location.href = `/meridians/${path.dataset.meridianId}/`;
  });
});
</script>

REST API 设计(DRF)

# serializers.py
class AcupointSerializer(serializers.ModelSerializer):
    class Meta:
        model = Acupoint
        fields = ['id', 'name', 'code', 'location']

# views.py
class MeridianViewSet(viewsets.ModelViewSet):
    queryset = Meridian.objects.all()
    serializer_class = MeridianSerializer

    @action(detail=True, methods=['get'])
    def acupoints(self, request, pk=None):
        meridian = self.get_object()
        acupoints = Acupoint.objects.filter(meridian=meridian)
        serializer = AcupointSerializer(acupoints, many=True)
        return Response(serializer.data)

穴位搜索(自动完成)

# views.py
class AcupointAutocomplete(autocomplete.Select2QuerySetView):
    def get_queryset(self):
        qs = Acupoint.objects.all()
        if self.q:
            qs = qs.filter(name__istartswith=self.q)
        return qs

数据可视化(Chart.js)

// 经络穴位数量统计
const ctx = document.getElementById('meridianChart').getContext('2d');
fetch('/api/meridians/stats/')
  .then(res => res.json())
  .then(data => {
    new Chart(ctx, {
      type: 'bar',
      data: {
        labels: data.labels,
        datasets: [{
          label: '穴位数量',
          data: data.counts,
          backgroundColor: '#e74c3c'
        }]
      }
    });
});

测试用例(模型验证)

# tests.py
class MeridianModelTest(TestCase):
    @classmethod
    def setUpTestData(cls):
        Meridian.objects.create(
            name="手太阴肺经",
            abbreviation="LU",
            description="起于中焦,下络大肠..."
        )

    def test_abbreviation_max_length(self):
        meridian = Meridian.objects.get(id=1)
        max_length = meridian._meta.get_field('abbreviation').max_length
        self.assertEqual(max_length, 10)

信号处理(图片缩略图生成)

# signals.py
@receiver(models.signals.post_save, sender=Meridian)
def create_meridian_thumbnail(sender, instance, **kwargs):
    if instance.image:
        img = Image.open(instance.image.path)
        img.thumbnail((300, 300))
        thumb_path = f"{instance.image.path}_thumb"
        img.save(thumb_path)

管理后台定制

# admin.py
class AcupointInline(admin.TabularInline):
    model = Acupoint
    extra = 1

@admin.register(Meridian)
class MeridianAdmin(admin.ModelAdmin):
    inlines = [AcupointInline]
    list_display = ('name', 'abbreviation', 'acupoint_count')
    
    def acupoint_count(self, obj):
        return obj.acupoint_set.count()

表单设计(带富文本编辑)

# forms.py
class MeridianForm(forms.ModelForm):
    description = forms.CharField(widget=CKEditorWidget())
    
    class Meta:
        model = Meridian
        fields = ['name', 'abbreviation', 'description', 'image']

权限控制(自定义权限)

# models.py
class Meridian(models.Model):
    # ... 其他字段 ...
    class Meta:
        permissions = [
            ("can_edit_meridian", "Can edit meridian details"),
            ("can_upload_image", "Can upload meridian images"),
        ]

任务队列(生成经络PDF)

# tasks.py
@shared_task
def generate_meridian_pdf(meridian_id):
    meridian = Meridian.objects.get(pk=meridian_id)
    html = render_to_string('tcm/meridian_pdf.html', {'meridian': meridian})
    pdf = HTML(string=html).write_pdf()
    with open(f'media/meridians/{meridian_id}.pdf', 'wb') as f:
        f.write(pdf)

国际化和本地化

# models.py
class Acupoint(models.Model):
    name = models.CharField(_("Acupoint Name"), max_length=50)
    location = models.TextField(_("Location Description"))
    # 其他字段...

缓存策略(经络列表缓存)

# views.py
@cache_page(60 * 15)
def meridian_list(request):
    meridians = Meridian.objects.all().prefetch_related('acupoint_set')
    return render(request, 'tcm/meridian_list.html', {'meridians': meridians})

日志记录(关键操作)

# views.py
logger = logging.getLogger('tcm.views')

def add_acupoint(request):
    if request.method == 'POST':
        form = AcupointForm(request.POST)
        if form.is_valid():
            acupoint = form.save()
            logger.info(f'Acupoint created: {acupoint.name}')
            return redirect('meridian_detail', pk=acupoint.meridian.id)


信号量(数据同步)

# signals.py
@receiver(post_save, sender=Acupoint)
def sync_to_elasticsearch(sender, instance, **kwargs):
    document = {
        'name': instance.name,
        'code': instance.code,
        'meridian': instance.meridian.name,
        'location': instance.location
    }
    es.index(index='acupoints', id=instance.id, body=document)


微信小程序 API

# api/views.py
class MiniProgramMeridianView(APIView):
    authentication_classes = [SessionAuthentication]
    
    def get(self, request):
        meridians = Meridian.objects.values('id', 'name', 'abbreviation')
        return Response({'data': list(meridians)})


数据导出(Excel 报表)

# views.py
def export_meridians(request):
    response = HttpResponse(content_type='application/ms-excel')
    response['Content-Disposition'] = 'attachment; filename="meridians.xlsx"'
    
    wb = Workbook()
    ws = wb.active
    ws.append(['ID', 'Name', 'Abbreviation', 'Acupoints Count'])
    
    for m in Meridian.objects.all():
        ws.append([m.id, m.name, m.abbreviation, m.acupoint_set.count()])
    
    wb.save(response)
    return response


实时通知(WebSocket)

# consumers.py
class MeridianConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        await self.accept()
        await self.channel_layer.group_add("meridians", self.channel_name)

    async def send_update(self, event):
        await self.send(text_data=json.dumps(event["data"]))


性能优化(select_related)

# views.py
def meridian_detail_optimized(request, pk):
    meri

网站公告

今日签到

点亮在社区的每一天
去签到