2010-06-29 5 views
0

Bonjour, J'ai créé mon premier champ de django personnalisé. C'est un champ de numéro de sécurité sociale (Cpr) suivant la syntaxe danois. Comme je suis nouveau à la fois python et django, j'aimerais avoir des commentaires sur le code!Commentaires voulus pour mon premier champ personnalisé 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

hmm Je suis confus, est-ce que demander des commentaires généraux sur un code compte comme une question? –

+1

Si vous avez de vraies questions à propos de votre code, par exemple: «Ma validation est-elle correcte? "Je pense que X est complexe, puis-je simplifier cela?", Nous serions heureux de vous aider, mais vraiment, SO n'est pas une alternative bon marché pour les analystes. – KillianDS

+0

Salut, merci pour les commentaires. Je suppose que la question est: "Comment puis-je améliorer ce code et le rendre plus pythonique et djangoish?". Être nouveau à la fois django et python c'est difficile d'être plus précis que ça. Thx cependant! –

Répondre

0

Y at-il une raison particulière pour laquelle vous combinez un widget Date avec le numéro CprP? Il semble qu'ils sont deux choses distinctes, et Django a déjà un SelectDateWidget décent. Je ne suis pas familier avec le nombre Cpr danois, mais à moins que la date fasse partie du nombre, ils devraient vraiment être deux champs séparés.

+0

Salut Chris, merci pour la réponse! Date _is_ partie du nombre et im en utilisant un simple widget textfield pour le rendre, c'est pourquoi. –

+0

Dans ce cas, je dirais que votre code semble bien. Vous pourriez envisager de contribuer à contrib.localflavor (http://docs.djangoproject.com/en/dev/ref/contrib/localflavor/) –

+0

Ah wauw, bonne chose une entrée danois n'existait pas déjà :) Je vais voir si je peut l'obtenir commis là. Merci beaucoup pour ce lien! –

Questions connexes