2010-06-29 95 views
0

嗨,我创建了我的第一个自定义Django字段。它是一个遵循丹麦语法的社会安全号码字段(Cpr)。由于我对python和django都很陌生,所以我很乐意在代码中获得一些反馈意见!反馈通缉我的第一个django自定义字段!

import django.forms as f 
from datetime import datetime 
import json 
from django.utils.safestring import mark_safe 
from django.core.exceptions import ValidationError 

# Globals 
YEAR = datetime.now().year   
FIELDS = (
    {'name' : "cpr_date", 'size': 2, 'maxlength': 2, 'renderfunc': None, 
     'field': f.IntegerField(min_value=1, max_value=31) 
    }, 
    {'name' : "cpr_month", 'size': 2, 'maxlength': 2, 'renderfunc': None, 
     'field': f.IntegerField(min_value=1, max_value=12), 
    },  
    {'name' : "cpr_year", 'size': 4, 'maxlength': 4, 
     'renderfunc': 'render_age', 
     'field': f.IntegerField(min_value=YEAR-120, max_value=YEAR), 
    }, 
    {'name' : "cpr_digits", 'size': 4, 'maxlength': 4, 
     'renderfunc': 'render_gender', 
     'field': f.IntegerField(min_value=1000, max_value=9999), 
    }, 
) 

class CprWidget(f.widgets.MultiWidget): 
    """Widget showing date, month, year and 4-last-digit fields for a danish cpr 
    number. 
    """ 
    def __init__(self, attrs=None): 
     widgets = [f.widgets.TextInput(field) for field in FIELDS] 
     super(CprWidget, self).__init__(widgets, attrs) 

    def decompress(self, v): 
     """Decompresses widget values to json before save""" 
     if v: return json.loads(v) 
     return [None, None, None, None] 

    def render(self, name, value, attrs=None): 
     """Extends with details rendered from parts of Cpr number""" 
     values = self.decompress_value(value) 
     output = super(CprWidget, self).render(name, value, attrs) 
     extra_output = "" 
     all_is_valid = True 
     i = 0 
     for field in FIELDS: 
      try: 
       value = values[i] 
       if value == None: 
        raise ValueError 
       fieldinst = field['field'] 
       fieldinst.validate(value) 
       fieldinst.run_validators(value) 
       if field['renderfunc']: 
        func = getattr(self, field['renderfunc']) 
        extra_output = extra_output + func(value) 
      except (IndexError, ValueError, ValidationError): 
       all_is_valid = False 
      finally: 
       i = i + 1 
     if all_is_valid: 
      extra_output = extra_output + self.render_cpr(values) 
     return output + mark_safe(extra_output) 

    def render_gender(self, value): 
     """Renders male or female based on last digit of Cpr""" 
     last_digit = int(str(value)[3]) 
     gender = (('Male','Female')[last_digit % 2 == 0]) 
     return self.render_line("Gender", gender) 

    def render_age(self, value): 
     """Renders age""" 
     return self.render_line("Age", YEAR-value) 

    def render_cpr(self, values): 
     """Renders full Cpr number""" 
     cpr = "%02d%02d%s-%s" % (
      int(values[0]), int(values[1]), str(values[2])[2:4], values[3]) 
     return self.render_line("Cpr", cpr) 

    def render_line(self, title, value): 
     """Renders a line with title and value""" 
     return "<br /><b>%s: </b>%s" % (title, value) 

    def decompress_value(self, value): 
     """Decompress values from value if needed""" 
     if not isinstance(value, list): 
      value = self.decompress(value) 
     return value 

    def format_output(self, rendered_widgets): 
     """Format html for widgets""" 
     labels = [u'Date', u'Month', u'Year', u'Digits'] 
     labels.reverse() 
     html = u'' 
     for w in rendered_widgets: html += labels.pop() + ': ' + str(w) 
     return html 

class CprField(f.MultiValueField): 
    """Field extending MultiValueField with date, month, year and 4-last-digit 
    fields for a danish cpr number. 
    """ 
    widget = CprWidget 
    def __init__(self, required=False, widget=None, label=None, initial=None): 
     fields = [field['field'] for field in FIELDS] 
     super(CprField, self).__init__(fields=fields, widget=widget, label=label 
      ,initial=initial, required=required) 

    def compress(self, data_list): 
     """Compress field values to json""" 
     return json.dumps(data_list) 
+0

嗯我很困惑,请问关于代码的一般反馈是否会成为一个问题? – 2010-06-29 10:00:38

+1

如果您有任何关于您的代码的实际问题,例如:'我的验证是否可用? “我认为X很复杂,我可以简化这个......”,我们很乐意提供帮助,但实际上,这不是便宜的分析师选择。 – KillianDS 2010-06-29 10:33:07

+0

嗨,thx评论。我想这个问题是:“我怎样才能改进这个代码,使它变得更加pythonic和djangoish?”。 django和python都是新手,所以比这更具体。 Thx虽然! – 2010-06-29 10:52:25

回答

0

是否有某些特定的原因,您将日期小部件与Cpr编号结合?看起来他们是两个单独的东西,Django已经有一个体面的SelectDateWidget。我不熟悉丹麦Cpr编号,但除非日期是编号的一部分,否则它们应该是两个独立的字段。

+0

嗨克里斯,thx的答复! Date_is_是数字的一部分,并且使用一个简单的文本字段小部件来呈现它,所以这就是为什么。 – 2010-06-29 14:31:26

+0

在这种情况下,我会说你的代码看起来不错。你可以考虑贡献一下contrib.localflavor(http://docs.djangoproject.com/en/dev/ref/contrib/localflavor/) – 2010-06-29 15:15:02

+0

啊哇,好东西丹麦条目还没有存在:)会看看我是否可以在那里实现它。 Thx很多链接! – 2010-06-29 15:21:51

相关问题