2014-04-30 10 views
5

मैं अपने Django प्रोजेक्ट में माप की विभिन्न प्रणालियों को लागू करना चाहता हूं, ताकि उपयोगकर्ता गीलेर चुन सकें, वे मीट्रिक या शाही इकाइयों का उपयोग करना चाहते हैं। हालांकि, मुझे नहीं पता कि ऐसा करने के लिए सही दृष्टिकोण क्या है।Django प्रोजेक्ट में माप की विभिन्न प्रणालियों की अवधारणा

वर्तमान में मेरे मॉडल में माप इकाई जागरूक फ़ील्ड नहीं हैं (वे पूर्णांक/दशमलव फ़ील्ड हैं) और मैं चाहूंगा कि मुझे सीधे अपने फ़ील्ड को बदलने की ज़रूरत नहीं है।

चूंकि मेरे वर्तमान डेटाबेस मान पहले से ही मीट्रिक मानों का प्रतिनिधित्व करते हैं, इसलिए मैं इसे इस तरह से रखने की योजना बना रहा हूं, जिसका अर्थ है कि मुझे उपयोगकर्ता इनपुट/मूल्य आउटपुट रूपांतरण को संभालना होगा। इस उद्देश्य के लिए Pint एक महान पुस्तकालय प्रतीत होता है।

क्या यह ऐप में फ़ील्ड संपादित किए बिना संभव है, लेकिन registration patterns या इसके बजाय कुछ और उपयोग कर रहा है? मैं जो हासिल करना चाहता हूं वह इस तरह कुछ है:

  1. मैं विभिन्न माप प्रकारों और संभावित मानों, जैसे कि लंबाई: मीटर, फीट धारण करने वाली डेटा संरचना को परिभाषित करता हूं; वजन: किलोग्राम, पाउंड इत्यादि
  2. मैं एक नई फ़ाइल "measments.py" या प्रत्येक ऐप निर्देशिका में समान कुछ जोड़ता हूं, जिसमें फ़ील्ड हैं जो माप मान रखते हैं। इस क्षेत्र में मैं परिभाषित कर सकता हूं कि सटीक माप फ़ील्ड क्या हैं और उनके प्रकार क्या हैं, जैसे फ़ील्ड = {mymodelfield: length, myothermodelfield: weight} आदि
  3. कुछ डिफ़ॉल्ट सेटिंग्स सेटिंग फ़ाइल में सेट की जा सकती हैं और ऐप में ओवरराइट की जा सकती हैं फ़ाइल, जैसे प्रत्येक माप के लिए डिफ़ॉल्ट इकाई (डेटाबेस जो डेटाबेस में संग्रहीत है)।
  4. उपयोगकर्ता प्रत्येक माप प्रकार के लिए अपनी वरीयता निर्धारित करता है। पिछले बिंदु में उल्लिखित प्रत्येक माप प्रकार के लिए डिफ़ॉल्ट इकाई है। प्राथमिकता/डिफ़ॉल्ट (संग्रहीत) इकाई मिलान के मामले में उपयोगकर्ता इनपुट को परिवर्तित करने के लिए तर्क आवश्यक है। बाउंड फॉर्म भी फील्ड वैल्यू को डिफॉल्ट से उपयोगकर्ता पसंदीदा इकाई में कनवर्ट करने में सक्षम होना चाहिए।

इस प्रकार का समाधान मौजूदा ऐप्स को प्लग करना आसान बनाता है क्योंकि ऐप में कोई फ़ील्ड और फॉर्म सीधे नहीं बदला जाएगा। पंजीकरण पैटर्न का उपयोग कर बुनियादी उदाहरण उपयोगी होंगे।

गैर-Django परियोजनाओं में यह कैसे किया जाता है, सामान्य विचारों और पैटर्न सहित किसी भी प्रासंगिक जानकारी का स्वागत है।

+0

मैं दान के जवाब के आधार पर कस्टम क्षेत्रों के साथ इकाई रूपांतरण प्राप्त करने में कामयाब रहे हैं और इस [recource] (http://tothinkornottothink.com/post/10815277049/django-forms-i- - एक नज़र कस्टम क्षेत्रों और विगेट्स में विस्तार)। –

उत्तर

3

जब से तुम तो केवल समय आप संभवतः कन्वर्ट करने के लिए जा रहे हैं मीट्रिक में स्टोर करने के लिए जारी रखना चाहते है:

  1. उपयोगकर्ता इनपुट
  2. उपयोगकर्ता

करने के लिए डेटा प्रदर्शित उपयोगकर्ता इनपुट के लिए आप कस्टम MultiValueField और कस्टम MultiWidget का उपयोग कर सकते हैं जो मीट्रिक मान आउटपुट करेगा।

from django import forms 
from django.forms import widgets,Form, CharField, MultiValueField, ChoiceField, DecimalField 

imperial = "imp" 
imperial_display = "Miles" 
metric = "met" 
metric_display = "Kilometers" 
unit_types = ((imperial, imperial_display), (metric, metric_display)) 

#You would use that library instead of this, and maybe not floats 
def to_imperial(val): 
    return float(val) * 1.60934 

def to_metric(val): 
    return float(val)/0.62137 

class NumberUnitWidget(widgets.MultiWidget): 
    def __init__(self, default_unit=None, attrs=None): 
     #I feel like this default_unit thing I'm doing is ugly 
     #but I couldn't think of another way to get the decompress 
     #to know which unit to convert to 
     self.default_unit = default_unit 

     _widgets = [ 
      widgets.NumberInput(attrs=attrs), 
      widgets.Select(attrs=attrs, choices=unit_types), 
     ] 
     super(NumberUnitWidget, self).__init__(_widgets, attrs) 

    #convert a single value to list for the form 
    def decompress(self, value): 
     if value: 
      if self.default_unit == imperial: 
       return [to_imperial(value), self.default_unit] 

      #value is the correct format 
      return [value, self.default_unit] 
     return [0, self.default_unit] 

class NumberUnitField(MultiValueField): 

    def __init__(self, *args, **kwargs): 
     _widget = NumberUnitWidget(default_unit=kwargs['initial'][0]) 
     fields = [ 
      DecimalField(label="Number!"), 
      ChoiceField(choices=unit_types) 
     ] 
     super(NumberUnitField, self).__init__(fields=fields, widget = _widget, *args, **kwargs) 


    def compress(self, values): 
     if values[1] == imperial: 
      #They inputed using imperial, convert to kilo 
      return to_metric(values[0]) 
     return values[0] #You dont need to convert because its in the format you want 

class TestForm(Form): 
    name = CharField() 
    num = NumberUnitField(initial=[None, metric]) 

TestForm में num के लिए मीट्रिक की डिफ़ॉल्ट सेटिंग ओवरराइट किया जा सकता है जब आप प्रपत्र initial={'num':[None,'imp']} का उपयोग कर का दृष्टांत ताकि जहां उनकी प्रोफ़ाइल से उपयोगकर्ताओं वरीयता डाल सकता है।

उपरोक्त फॉर्म का उपयोग करते समय जब आप देखते हैं कि फॉर्म is_valid() वह फ़ॉर्म आपके पास वापस लौटाएगा, तो वह मेट्रिक में होगा।

उपयोगकर्ता प्रपत्र यह एक Django NumberInput डिफ़ॉल्ट सेटिंग पहले से ही चयनित के साथ एक का चयन के बाद रूप में दिखाई देगा देखता है।

डेटा आप एक template filter इस्तेमाल कर सकते हैं प्रदर्शित करने के लिए

{{a_value|convert_units:user_pref}} 

बेशक यह सब सिर्फ मील/किलोमीटर परिवर्तित किया जाता है: यहाँ एक सरल एक आप जानकारी देने के लिए

from django import template 
register = template.Library() 
@register.filter 
def convert_units(value, user_pref): 
    #You probably want to use that library you found here to do conversions 
    #instead of what i've used. 
    if user_pref == "met": 
     return str(value) + " Kilometers" 
    else: 
     return str(float(value)/ 1.60934) + " Miles" 

फिर टेम्पलेट में यह कुछ ऐसा दिखाई देगा है। आपको विजेट/फ़ील्ड को डुप्लिकेट और चेंज या सबक्लास करना होगा और शायद पाउंड/किलोग्राम जैसी अन्य चीज़ों को कवर करने के लिए कुछ और टेम्पलेट फ़िल्टर होंगे।

+0

विस्तृत उत्तर के लिए धन्यवाद! मैं यह देखने के लिए आज इस पर काम करूंगा कि यह कैसा चल रहा है। पी.एस. क्या इस मामले में पहले उल्लिखित पंजीकरण पैटर्न का उपयोग करना संभव होगा? जैसे खोज इंडेक्स के साथ Haystack खोज क्या करता है के समान कुछ? –

+0

इन प्रपत्रों को अपने मॉडल के साथ जोड़ने के लिए? यह लेकिन आप ModelForm https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#modelform पर एक नज़र रखना चाहिए सकता है। –

0

मैं सिर्फ इतना है कि इसके बाद के संस्करण के लिए पिंट और Django, बिल्कुल उसी प्रकार एकीकृत pypi एक छोटे पुस्तकालय प्रकाशित किया है। >

https://github.com/bharling/django-pint/

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