You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django视图中合并重复context代码以遵循DRY原则?

Django视图中Context的DRY优化方案

问题背景

希望在Django视图的return render语句中选择性合并context,遵循DRY(不要重复自己)原则简化带角色权限判断的视图代码,避免各分支重复编写相同的context内容。

原show视图代码

def show(request):

    now_day = datetime.date.today()
    current_user = request.user 

    if request.method == 'GET':

        if view_self(current_user) == True and more_rights(current_user) == False:
            if Employees.objects.filter(employee_number=current_user).exists():

                context = {'names': Employees.objects.filter(employee_number=current_user)}
            else:
                context = {'info': "Für sie existiert (noch) kein Datensatz in dieser Datenbank"}  
        else: 
            context = {'names': Employees.objects.all().order_by('last_name').values()}

        return render(request, 'show.html', context)

    else:
        if view_self(current_user) == True and more_rights(current_user) == False:

            if request.POST['id'] == 'Mitarbeiter auswählen...':
                context = {
                    'names': Employees.objects.filter(employee_number=current_user),
                    'info': "Bitte treffen Sie zuerst eine Auswahl"
                }
            else:
                employee = request.POST['id']
                context = {
                    'names': Employees.objects.filter(employee_number=current_user),
                    'entries': Employees.objects.filter(id=request.POST['id']),
                    'work_conditions': Employment.objects.filter(employee_id=request.POST['id']),
                    'functions': Functions.objects.filter(employee__functions=request.POST['id']).order_by('function'),
                    'fieldsoa': FieldsOfActivity.objects.filter(employee__fieldsofactivity=request.POST['id']).order_by('field_of_activity'),
                    'missions': Foreign_Missions.objects.filter(employee_id=request.POST['id']).order_by('-begin'),
                    'examinations': Examinations.objects.filter(employee_id=request.POST['id']).order_by('-date'),
                    'total_duration_days': Foreign_Missions.objects.total_duration_days(employee),
                    'today': now_day,
                    'special_header': "Datensätze anzeigen"
                }

        elif request.POST['id'] == 'Mitarbeiter auswählen...':
            context = {
            'names': Employees.objects.all().order_by('last_name').values(),
            'info': "Bitte treffen Sie zuerst eine Auswahl"
            }
    
        elif 'id' in request.POST:
            employee = request.POST['id']             #Employees.objects.get(pk=id)
            context = {
            'names': Employees.objects.all().order_by('last_name').values(),
            'entries': Employees.objects.filter(id=request.POST['id']),
            'work_conditions': Employment.objects.filter(employee_id=request.POST['id']),
            'functions': Functions.objects.filter(employee__functions=request.POST['id']).order_by('function'),
            'fieldsoa': FieldsOfActivity.objects.filter(employee__fieldsofactivity=request.POST['id']).order_by('field_of_activity'),
            'missions': Foreign_Missions.objects.filter(employee_id=request.POST['id']).order_by('-begin'),
            'examinations': Examinations.objects.filter(employee_id=request.POST['id']).order_by('-date'),
            'total_duration_days': Foreign_Missions.objects.total_duration_days(employee),
            'today': now_day,
            'special_header': "Datensätze anzeigen"
            }

        return render(request, 'show.html', context)

原delete视图代码

def delete(request):

context = {}
context['names'] = Employees.objects.all().order_by('last_name').values(),

if request.method == 'GET':
    context = {
        # 'names': Employees.objects.all().order_by('last_name').values(),
        'special_header': "Datensätze löschen",
    }
    
# Wenn der Button ohne Auswahl gedrückt wird
elif 'id' in request.POST and request.POST['id'] == 'Mitarbeiter löschen...':
    context = {
        # 'names': Employees.objects.all().order_by('last_name').values(),
        'info': "Bitte treffen Sie zuerst eine Auswahl"
    }

else:
    id = request.POST['id']
    lastname = Employees.objects.get(id=id).last_name.upper()
    firstname = Employees.objects.get(id=id).first_name
    trash = Employees.objects.filter(id=id)
    # trash.delete()

    context = {
        # 'names': Employees.objects.all().order_by('last_name').values(),
        'success': "Datensatz für " + lastname + ", " + firstname + " wurde gelöscht"
    }

return render(request, 'delete.html', context)

优化方案

核心思路:先初始化基础context(包含所有分支共有的字段),再根据不同业务分支追加/修改特定字段,避免重复定义完整的context字典。

1. show视图优化

def show(request):
    now_day = datetime.date.today()
    current_user = request.user
    # 提前计算权限判断结果,避免重复写长条件
    is_self_only = view_self(current_user) and not more_rights(current_user)
    
    # 初始化基础context,先处理所有分支都可能用到的names字段
    context = {}
    if is_self_only:
        # 先查询当前用户的员工记录
        self_employees = Employees.objects.filter(employee_number=current_user)
        if self_employees.exists():
            context['names'] = self_employees
        else:
            context['info'] = "Für sie existiert (noch) kein Datensatz in dieser Datenbank"
    else:
        context['names'] = Employees.objects.all().order_by('last_name').values()

    if request.method == 'GET':
        return render(request, 'show.html', context)
    
    # 处理POST请求
    post_id = request.POST.get('id')
    if is_self_only:
        if post_id == 'Mitarbeiter auswählen...':
            # 只追加info字段,保留已有的names
            context['info'] = "Bitte treffen Sie zuerst eine Auswahl"
        else:
            # 追加详细数据字段
            employee = post_id
            context.update({
                'entries': Employees.objects.filter(id=post_id),
                'work_conditions': Employment.objects.filter(employee_id=post_id),
                'functions': Functions.objects.filter(employee__functions=post_id).order_by('function'),
                'fieldsoa': FieldsOfActivity.objects.filter(employee__fieldsofactivity=post_id).order_by('field_of_activity'),
                'missions': Foreign_Missions.objects.filter(employee_id=post_id).order_by('-begin'),
                'examinations': Examinations.objects.filter(employee_id=post_id).order_by('-date'),
                'total_duration_days': Foreign_Missions.objects.total_duration_days(employee),
                'today': now_day,
                'special_header': "Datensätze anzeigen"
            })
    else:
        if post_id == 'Mitarbeiter auswählen...':
            context['info'] = "Bitte treffen Sie zuerst eine Auswahl"
        elif post_id:
            employee = post_id
            context.update({
                'entries': Employees.objects.filter(id=post_id),
                'work_conditions': Employment.objects.filter(employee_id=post_id),
                'functions': Functions.objects.filter(employee__functions=post_id).order_by('function'),
                'fieldsoa': FieldsOfActivity.objects.filter(employee__fieldsofactivity=post_id).order_by('field_of_activity'),
                'missions': Foreign_Missions.objects.filter(employee_id=post_id).order_by('-begin'),
                'examinations': Examinations.objects.filter(employee_id=post_id).order_by('-date'),
                'total_duration_days': Foreign_Missions.objects.total_duration_days(employee),
                'today': now_day,
                'special_header': "Datensätze anzeigen"
            })

    return render(request, 'show.html', context)

优化点说明:

  • 提前计算is_self_only变量,避免重复编写权限判断逻辑
  • 先初始化基础的names或info字段,各分支只需追加差异字段
  • 使用context.update()批量追加字段,替代重复定义完整字典
  • 用request.POST.get('id')替代直接索引,避免KeyError

2. delete视图优化

原问题是每次重新赋值context导致基础的names字段被覆盖,优化后:

def delete(request):
    # 初始化基础context,包含所有分支都需要的names字段
    context = {
        'names': Employees.objects.all().order_by('last_name').values()
    }

    if request.method == 'GET':
        # 仅新增special_header字段,保留原有names
        context['special_header'] = "Datensätze löschen"
    
    elif 'id' in request.POST:
        post_id = request.POST['id']
        if post_id == 'Mitarbeiter löschen...':
            context['info'] = "Bitte treffen Sie zuerst eine Auswahl"
        else:
            # 获取员工信息,优化查询减少DB访问
            employee = Employees.objects.get(id=post_id)
            # trash = employee  # 直接用实例
            # trash.delete()
            context['success'] = f"Datensatz für {employee.last_name.upper()}, {employee.first_name} wurde gelöscht"

    return render(request, 'delete.html', context)

优化点说明:

  • 先初始化包含names的基础context,所有分支都不会覆盖这个字段
  • 用context['key'] = value追加字段,替代重新定义完整字典
  • 优化员工信息查询,从两次get改为一次,减少数据库访问

内容的提问来源于stack exchange,提问作者Krallenkroete

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 23:27:50