2011-10-30 19 views
7

मुझे यह समझने में समस्या हो रही है कि django व्यू में कस्टम फॉर्म फ़ील्ड को कैसे प्रारंभ किया जाए।Django कस्टम फॉर्म फ़ील्ड प्रारंभिक डेटा

उदाहरण के लिए: http://djangosnippets.org/snippets/907/

from datetime import date, datetime 
from calendar import monthrange 

class CreditCardField(forms.IntegerField): 
    @staticmethod 
    def get_cc_type(number): 
     number = str(number) 
     #group checking by ascending length of number 
     if len(number) == 13: 
      if number[0] == "4": 
       return "Visa" 
     return "Unknown" 

    def clean(self, value): 
     if value and (len(value) < 13 or len(value) > 16): 
      raise forms.ValidationError("Please enter in a valid "+\ 
       "credit card number.") 
     elif self.get_cc_type(value) not in ("Visa", "MasterCard", 
              "American Express"): 
      raise forms.ValidationError("Please enter in a Visa, "+\ 
       "Master Card, or American Express credit card number.") 
     return super(CreditCardField, self).clean(value) 

class CCExpWidget(forms.MultiWidget): 
    """ Widget containing two select boxes for selecting the month and year""" 
    def decompress(self, value): 
     return [value.month, value.year] if value else [None, None] 

    def format_output(self, rendered_widgets): 
     html = u'/'.join(rendered_widgets) 
     return u'<span style="white-space: nowrap">%s</span>' % html 


class CCExpField(forms.MultiValueField): 
    EXP_MONTH = [(x, x) for x in xrange(1, 13)] 
    EXP_YEAR = [(x, x) for x in xrange(date.today().year, 
             date.today().year + 15)] 
    default_error_messages = { 
     'invalid_month': u'Enter a valid month.', 
     'invalid_year': u'Enter a valid year.', 
    } 

    def __init__(self, *args, **kwargs): 
     errors = self.default_error_messages.copy() 
     if 'error_messages' in kwargs: 
      errors.update(kwargs['error_messages']) 
     fields = (
      forms.ChoiceField(choices=self.EXP_MONTH, 
       error_messages={'invalid': errors['invalid_month']}), 
      forms.ChoiceField(choices=self.EXP_YEAR, 
       error_messages={'invalid': errors['invalid_year']}), 
     ) 
     super(CCExpField, self).__init__(fields, *args, **kwargs) 
     self.widget = CCExpWidget(widgets = 
      [fields[0].widget, fields[1].widget]) 

    def clean(self, value): 
     exp = super(CCExpField, self).clean(value) 
     if date.today() > exp: 
      raise forms.ValidationError(
      "The expiration date you entered is in the past.") 
     return exp 

    def compress(self, data_list): 
     if data_list: 
      if data_list[1] in forms.fields.EMPTY_VALUES: 
       error = self.error_messages['invalid_year'] 
       raise forms.ValidationError(error) 
      if data_list[0] in forms.fields.EMPTY_VALUES: 
       error = self.error_messages['invalid_month'] 
       raise forms.ValidationError(error) 
      year = int(data_list[1]) 
      month = int(data_list[0]) 
      # find last day of the month 
      day = monthrange(year, month)[1] 
      return date(year, month, day) 
     return None 


class PaymentForm(forms.Form): 
    number = CreditCardField(required = True, label = "Card Number") 
    holder = forms.CharField(required = True, label = "Card Holder Name", 
     max_length = 60) 
    expiration = CCExpField(required = True, label = "Expiration") 
    ccv_number = forms.IntegerField(required = True, label = "CCV Number", 
     max_value = 9999, widget = forms.TextInput(attrs={'size': '4'})) 

    def __init__(self, *args, **kwargs): 
     self.payment_data = kwargs.pop('payment_data', None) 
     super(PaymentForm, self).__init__(*args, **kwargs) 

    def clean(self): 
     cleaned = super(PaymentForm, self).clean() 
     if not self.errors: 
      result = self.process_payment() 
      if result and result[0] == 'Card declined': 
       raise forms.ValidationError('Your credit card was declined.') 
      elif result and result[0] == 'Processing error': 
       raise forms.ValidationError(
        'We encountered the following error while processing '+\ 
        'your credit card: '+result[1]) 
     return cleaned 

    def process_payment(self): 
     if self.payment_data: 
      # don't process payment if payment_data wasn't set 
      datadict = self.cleaned_data 
      datadict.update(self.payment_data) 

      from virtualmerchant import VirtualMerchant 
      vmerchant = VirtualMerchant(datadict) 

      return vmerchant.process_virtualmerchant_payment() 

ऊपर के उदाहरण भुगतान प्रपत्र में, आप PaymentForm.expiration क्षेत्र के लिए प्रारंभिक डेटा कैसे पास होता?

मुझे पता है तुम कर सकते हैं:

c = PaymentForm({'number':'1234567890', 'holder':'Bob Barker','ccv_number':'123'}) 

हालांकि, कैसे आप डेटा एक कस्टम फ़ील्ड के लिए इस तरह यहां लागू किया एक के रूप में पारित करते हैं? ताकि आप सेट है कि भले ही यह एक कस्टम फ़ील्ड है

https://code.djangoproject.com/browser/django/trunk/django/forms/fields.py#L45

ताकि आप केवल निर्माता अधिलेखित करने के लिए सक्षम होना चाहिए

+1

मुझे समझ में नहीं आता आपको लगता है कि यह किसी अन्य क्षेत्र से अलग क्यों होगा। [मेरे अन्य उत्तर] (http://stackoverflow.com/questions/936376/prepopulate-django-non-model-form/936622#936622) में उल्लिखित फॉर्म को तुरंत चालू करते समय 'प्रारंभिक' का उपयोग करें, जिस पर आपने टिप्पणी की थी। –

+0

@DanielRoseman: प्रारंभिक डेटा के साथ PaymentForm.expiration को पूर्ववत करने के लिए ऊपर परिभाषित भुगतानफॉर्म को मैं क्या पास करूंगा? मैंने सी = पेमेंटफॉर्म ({'समाप्ति': '01/2011'}) और अन्य संयोजनों की कोशिश की और इसे पूर्ववत करने में असमर्थ था इसलिए मैं इस सवाल से पूछ रहा हूं। – Chris

उत्तर

7

सभी फ़ील्ड एक 'प्रारंभिक' विशेषता है:

class PaymentForm(forms.Form): 
    def __init__(self, exp = None, *args, **kwargs): 
     super(PaymentForm, self).__init__(*args, **kwargs) 
     if exp: 
      self.fields['expiration'].initial = exp 

और आपके विचार में आप आवश्यक डेटा पास कर सकते हैं:

form = PaymentForm(exp=...) 
+0

यह समझ में आता है लेकिन सीसीईएक्सपीएफआईल्ड को वह डेटा मिलता है जो मुझे समझ में नहीं आता है। आपके उत्तर में, मेरा भुगतान फॉर्म जब "एक्सप" तर्क के लिए चेक प्रारंभ करता है और यदि पास हो जाता है, तो उसे पेमेंटफॉर्म.एक्सपीशन फ़ील्ड पर भेज दिया जाता है। इस बिंदु पर PaymentForm.expiration जो एक CCExpField है, वह डेटा अपने 2 चार फ़ील्ड में प्राप्त करता है। – Chris

+1

सीसीईएक्सपीफ़िल्ड को यहां डेटा दिया गया है: self.fields ['समाप्ति']। प्रारंभिक = एक्सप जहां फ़ील्ड ऑब्जेक्ट की 'प्रारंभिक' विशेषता सेट की गई है। बाद में इसे विजेट के रूप में प्रदर्शित करने के लिए खिलाया जाता है यदि कुछ भी पहले सहेजा नहीं गया है। –

संबंधित मुद्दे