Django import-export在用户csv上传之前生成用户名

时间:2017-01-31 16:31:17

标签: django csv django-import-export

我需要从csv文件批量生成我的应用程序的用户。我的csv包含以下字段:

last_name,first_name,email

要生成用户名,我有一个我希望在“脱水”中使用的功能。方法。脱水方法仅适用于出口,而不适用于进口。

[编辑] 在@ sanca-kembang给出了下面的答案之后,这就是我最终做的事情。下面的例子非常有效(django 1.10.5,python 3.6.0)。

tools.py

from django.contrib.auth.models import User

def generate_username(first_name, last_name):

    fname = first_name.lower()
    lname = last_name.lower()

    prefix = "%s%s" % (fname[0], lname)
    username = prefix
    i = 2
    while User.objects.filter(username = username).exists():
        username = "%s%d" % (prefix, i)
        i += 1
    return username

admin.py

from django.contrib.auth.models import User
from import_export import resources, widgets
from import_export.admin import ImportExportModelAdmin
from .tools import generate_username


class UserResource(resources.ModelResource):

    class Meta:
        model = User
        skip_unchanged = True
        report_skipped = True
        fields = ('id', 'last_name', 'first_name', 'email', 'username')

    def import_obj(self, obj, data, dry_run):
        first_name = data.get('first_name')
        last_name = data.get('last_name')
        username = generate_username(first_name, last_name)
        for field in self.get_fields():
            if isinstance(field.widget, widgets.ManyToManyWidget):
                continue
            if field.column_name == 'username':
                data.update({'username': username})
            print(obj)

            self.import_field(field, obj, data)

class UserAdmin(ImportExportModelAdmin):  
    resource_class = UserResource     

admin.site.unregister(User)
admin.site.register(User, UserAdmin)

1 个答案:

答案 0 :(得分:3)

我检查了源代码,我在导入和导出之间找到了一种不同的方法...... export_field的函数具有dehydrate_属性,但import_field没有...... < / p>

导出: https://github.com/django-import-export/django-import-export/blob/master/import_export/resources.py#L590-L595

def export_field(self, field, obj):
    field_name = self.get_field_name(field)
    method = getattr(self, 'dehydrate_%s' % field_name, None)
    if method is not None:
        return method(obj)
    return field.export(obj)

导入: https://github.com/django-import-export/django-import-export/blob/master/import_export/resources.py#L315-L321

def import_field(self, field, obj, data):
    """
    Calls :meth:`import_export.fields.Field.save` if ``Field.attribute``
    and ``Field.column_name`` are found in ``data``.
    """
    if field.attribute and field.column_name in data:
        field.save(obj, data)

我认为你需要覆盖import_obj的功能,这是你案例的一个例子:

from import_export import resources, widgets
from import_export.admin import ImportExportModelAdmin

# your package imported

class UserResource(resources.ModelResource):

    class Meta:
        model = User
        ....

    def dehydrate_username(self, user):
         # your unfinish code got here, 
         # if you want to enable for export mode...
         # username = generate_username_function here
         return username

    def import_obj(self, obj, data, dry_run):
        """
        Traverses every field in this Resource and calls
        :meth:`~import_export.resources.Resource.import_field`.
        """
        for field in self.get_fields():
            if isinstance(field.widget, widgets.ManyToManyWidget):
                continue

            # find specific `field_name`
            # param of `data` is OrderDict
            if field.column_name == 'username':
                data.update({'username': 'Hello %s' % data.get('username')})
            # checkout the changed object
            print(obj)

            self.import_field(field, obj, data)

这是我的测试...

test import export

  

另见这个类似的问题; https://github.com/django-import-export/django-import-export/issues/51

希望它有用......