1

在 ModelForm 中,我可以编写一个clean_<field_name>成员函数来自动验证和清理用户输入的数据,但是在manage.py loaddata.

4

2 回答 2

3

假设加载的夹具loaddata包含不需要验证的干净数据(通常作为先验的逆操作dumpdata),因此简短的回答是,如果您需要清理输入,则 loaddata 不是您想要的方法。

但是,您可能可以在实现自定义数据清理代码时使用 loaddata 的一些基础——我相信您可以使用 Django序列化库轻松编写脚本来读取现有数据文件并正常保存生成的对象数据清理完毕后。

于 2012-07-26T20:54:19.550 回答
0

如果其他人想做类似的事情,我定义了一个模型方法来进行清理(因此可以从 ModelForms 调用它)

MAX_ZIPCODE_DIGITS = 9
MIN_ZIPCODE_DIGITS = 5

def clean_zip_code(self, s=None):
    #s = str(s or self.zip_code)
    if not s: return None
    s = re.sub("\D","",s)
    if len(s)>self.MAX_ZIPCODE_DIGITS: 
        s = s[:self.MAX_ZIPCODE_DIGITS]
    if len(s) in (self.MIN_ZIPCODE_DIGITS-1,self.MAX_ZIPCODE_DIGITS-1):
        s = '0'+s # FIXME: deal with other intermediate lengths
    if len(s)>=self.MAX_ZIPCODE_DIGITS:
        s = s[:self.MIN_ZIPCODE_DIGITS]+'-'+s[self.MIN_ZIPCODE_DIGITS:] 
    return s

clean_然后编写了一个独立的 python 脚本来使用模型中找到的任何方法来清理我的遗留 json 文件。

import os, json

def clean_json(app = 'XYZapp', model='Entity', fields='zip_code', cleaner_prefix='clean_'):
    # Set the DJANGO_SETTINGS_MODULE environment variable.
    os.environ['DJANGO_SETTINGS_MODULE'] = app+".settings"
    settings = __import__(app+'.settings').settings
    models   = __import__(app+'.models').models

    fpath    = os.path.join( settings.SITE_PROJECT_PATH, 'fixtures', model+'.json')
    if isinstance(fields,(str,unicode)):
        fields = [fields]
    Ns = []
    for field in fields:
        try:
            instance = getattr(models,model)()
        except AttributeError:
            print 'No model named %s could be found'%(model,)
            continue
        try:
            cleaner = getattr(instance, cleaner_prefix+field)
        except AttributeError:
            print 'No cleaner method named %s.%s could be found'%(model,cleaner_prefix+field)
            continue
        print 'Cleaning %s using %s.%s...'%(fpath,model,cleaner.__name__)
        fin = open(fpath,'r')
        if fin:
            l = json.load(fin)
            before = len(l)
            cleans = 0
            for i in range(len(l)):
                if 'fields' in l[i] and field in l[i]['fields']:
                    l[i]['fields'][field]=cleaner(l[i]['fields'][field]) # cleaner returns None to delete records
                    cleans += 1
            fin.close()
            after = len(l)
            assert after>.5*before
            Ns += [(before, after,cleans)]
            print 'Writing %d/%d (new/old) records after %d cleanups...'%Ns[-1]
            with open(fpath,'w') as fout:
                fout.write(json.dumps(l,indent=2,sort_keys=True))
    return Ns

if __name__ == '__main__':
    clean_json()
于 2012-07-27T17:54:21.283 回答