Django:如何使用 filter() 或不基于可选参数?

Django: How to use filter() or not based at optional param?

正如您在此 url city 中看到的那样,参数是可选的:

re_path(r'all/(?P<category>\w+)/(?P<page_num>\w+)/?/(?P<city>\d+)?', views.show_all_objects, name="show-all-objects")

views.py:

def show_all_objects(request, category, page_num, city=''):
    if category == 'restaurants':
        objects = Item.objects.instance_of(Restaurant)
    elif category == 'sportfitness':
        objects = Item.objects.instance_of(SportFitness)
    elif category == 'carservice':
        objects = Item.objects.instance_of(CarService)
    elif category == 'beautysalon':
        objects = Item.objects.instance_of(BeautySalon)
    elif category == 'fastfood':
        objects = Item.objects.instance_of(FastFood)
    elif category == 'carwash':
        objects = Item.objects.instance_of(CarWash)
    elif category == 'fun':
        objects = Item.objects.instance_of(Fun)
    elif category == 'other':
        objects = Item.objects.instance_of(Other)

    paginator = Paginator(objects, 2)
    objects = paginator.get_page(page_num)

    context = {
        'objects': objects,
        'category': category,
        'page_num': page_num,
    }

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

我想如果 city 参数设置为添加 .filter(city=city),我可以使用 if/else 但它不遵循 DRY 原则。

以下会出现什么问题?:

def show_all_objects(request, category, page_num, city=''):
    if category == 'restaurants':
        objects = Item.objects.instance_of(Restaurant)
    elif category == 'sportfitness':
        objects = Item.objects.instance_of(SportFitness)
    elif category == 'carservice':
        objects = Item.objects.instance_of(CarService)
    elif category == 'beautysalon':
        objects = Item.objects.instance_of(BeautySalon)
    elif category == 'fastfood':
        objects = Item.objects.instance_of(FastFood)
    elif category == 'carwash':
        objects = Item.objects.instance_of(CarWash)
    elif category == 'fun':
        objects = Item.objects.instance_of(Fun)
    elif category == 'other':
        objects = Item.objects.instance_of(Other)

    # The only difference is these two lines:
    if city:
        objects = objects.filter(city=city)    

    paginator = Paginator(objects, 2)
    objects = paginator.get_page(page_num)

    context = {
        'objects': objects,
        'category': category,
        'page_num': page_num,
    }

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

尝试使用字典来映射 instance_of 方法的参数。

def show_all_objects(request, category, page_num, city=''):

    params_map = {
        'restaurants': Restaurant,
        'sportfitness': SportFitness,
        'carservice': CarService,
        'beautysalon': BeautySalon,
        'fastfood': FastFood,
        'carwash': CarWash,
        'fun': Fun,
        'other': Other,
    }

    objects = Item.objects.instance_of(params_map.get(category))

    # If city is provided
    if city:
        objects = objects.filter(city=city)    

    paginator = Paginator(objects, 2)
    objects = paginator.get_page(page_num)

    context = {
        'objects': objects,
        'category': category,
        'page_num': page_num,
    }

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