【问题标题】:Django: How do I exclude related fields when using `._meta.get_fields()`?Django:使用`._meta.get_fields()`时如何排除相关字段?
【发布时间】:2021-07-11 11:08:49
【问题描述】:

我正在尝试在 Django 中编写一个视图以将我的模型数据导出到 csv 文件中。

问题是我不知道如何排除相关字段。目前,当我运行model._meta.get_fields() 时,该函数返回模型的字段 相关模型的字段,因此当我使用相关字段的名称使用getattr() 时,我的视图会引发错误。

我尝试使用.is_related() 排除相关字段,但这也排除了模型字段(如 ForeignKey)。

当我调用字段名时,我可以看到类名是ManyToOneRel,但我不知道如何访问该属性。

有谁知道如何排除相关字段或判断一个字段是否是相关模型的字段?

下面是我的观点。

感谢任何可以提供帮助的人!

class CSVExportView(View):
    template_name = 'medrec_v2/csv_export.html'

    def get(self, request, *args, **kwargs):
        model_list = [m for m in apps.app_configs['medrec_v2'].models if '_' not in m ] 
        # print(model_list)
        context = {'model_list':model_list}
        return render(request, self.template_name, context)

    def post(self, request, *args, ):
        model_name = request.POST.get("model-sel")
        model = apps.get_model(app_label='medrec_v2',model_name=model_name)
        content_type = 'text/csv'
        datecode = datetime.today().strftime('%y%m%d')
        file_name = f'{datecode}_medrecv2_{model_name}.csv'

        response = HttpResponse(content_type = content_type)
        response['Content-Disposition'] = f'attachment; filename="{file_name}"'
        header = [f.name.split('.')[-1] for f in model._meta.get_fields() if f.is_relation == False]
        print(header)
        writer = csv.writer(response)
        writer.writerow(header)
        i=0
        for instance in model.objects.all():
            row = []
            for field in instance._meta.get_fields(include_parents=False):
                if field.is_relation == False:
                    val = getattr(instance, field.name)
                    if val is None:
                        val = ''
                    row.append(val)
            writer.writerow(row)

        
        return response


【问题讨论】:

    标签: python django csv django-models


    【解决方案1】:

    RelatedField 有标志:

    class RelatedField(FieldCacheMixin, Field):
        """Base class that all relational fields inherit from."""
    
        # Field flags
        one_to_many = False
        one_to_one = False
        many_to_many = False
        many_to_one = False
    

    然后你可以检查这些条件:

    for field in instance._meta.get_fields(include_parents=False):
        if field.concrete and not(
                field.is_relation or field.one_to_one or 
                (field.many_to_one and field.related_model)):
            val = getattr(instance, field.name)
            if val is None:
                val = ''
            row.append(val)

    【讨论】:

    • 完美!实际上,我只需要field.concrete,因为我仍然想要模型中的外键/多对多字段。这清除了函数中的所有相关字段。
    • 出于好奇,我昨天花了几个小时寻找这个问题的答案,包括 Django 文档,但我没有遇到model.concrete一次。您是否可以使用资源或参考来弄清楚这些类型的事情,还是只是来自经验?
    • @StephenKoplin,可以在这里找到:docs.djangoproject.com/en/dev/ref/models/fields/…
    猜你喜欢
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 2021-07-11
    • 2019-03-09
    • 2013-12-03
    • 1970-01-01
    • 2017-07-13
    相关资源
    最近更新 更多