编写可重用的视图

时间:2014-03-29 19:56:29

标签: python django csv model-view-controller

我有这个功能需要QuerySet并呈现CSV。我想写一个视图,提供一个模板,其中包含下载不同CSV文件的选项(基本上是 models.py 中定义的任何内容)

# Exports CSV file using a QuerySet
def export(qs, fields=None, file_name='data'):
    model = qs.model
    response = HttpResponse(mimetype='text/csv')
    response['Content-Disposition'] = 'attachment; filename={0}-{1}.csv'.format(file_name, str(datetime.date.today()))
    writer = csv.writer(response)
    # Write headers to CSV file
    if fields:
        headers = fields
    else:
        headers = []
        for field in model._meta.fields:
            headers.append(field.name)
    writer.writerow(headers)
    # Write data to CSV file
    for obj in qs:
        row = []
        for field in headers:
            if field in headers:
                val = getattr(obj, field)
                if callable(val):
                    val = val()
                row.append(val)
        writer.writerow(row)
    # Return CSV file to browser as download
    return response

目前我正在编写一个不可重复使用的视图:

def csv_of_surveys(request):
    r = export(Survey.objects.all(), file_name='surveys')
    return r

我该怎么办?我唯一的想法是发送一个代码并写一个switch语句,所以

{% url "csv_of" 0 %}
{% url "csv_of" 1 %}
{% url "csv_of" 2 %}
{% url "csv_of" 3 %}

其中0,1,2和3对应于下载不同的东西。

新视图看起来像:

def csv_of(request, code):
    if code == 0:
        r = export(Survey.objects.all(), file_name='surveys')
        return r
    elif code == 1:
        r = export(User.objects.all(), file_name='teachers')
        return r
    elif code == 2:
        r = export(Student.objects.all(), file_name='students')
        return r
    # ...
    else:
        return HttpResponseRedirect('/')

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

创建一个字典,将给定代码映射到关联对象,然后将所有if语句减少为一个if。对于文件名,看起来你每次都做同样的事情,这是多元化和小写它,在这种情况下你应该在model._meta.verbose_name_plural中设置它,然后在你需要时访问它:< / p>

file_codes = {0:Survey,1:User...}
def csv_of(request, code):
  if int(code) in file_codes.keys():
    obj = file_codes[int(code)]
    return export(obj.objects.all(), file_name = obj._meta.verbose_name_plural.title())
  else:
    return HttpResponseRedirect('/')