2013-07-16 10 views
24

पर एक गणना फ़ील्ड जोड़ने के लिए मेरे पास एक साधारण Employee मॉडल है जिसमें firstname, lastname और middlename फ़ील्ड शामिल हैं। जैसे परिकलित क्षेत्र बनाने के द्वाराएक Django मॉडल

lastname, firstname middlename 
मेरे लिए

तार्किक जगह इस मॉडल में है क्या करने के लिए:

व्यवस्थापक तरफ और संभावना कहीं और, मैं प्रदर्शित करने के लिए के रूप में है कि चाहते हैं

from django.db import models 
from django.contrib import admin 

class Employee(models.Model): 
    lastname = models.CharField("Last", max_length=64) 
    firstname = models.CharField("First", max_length=64) 
    middlename = models.CharField("Middle", max_length=64) 
    clocknumber = models.CharField(max_length=16) 
    name = ''.join(
     [lastname.value_to_string(), 
     ',', 
     firstname.value_to_string(), 
     ' ', 
     middlename.value_to_string()]) 

    class Meta: 
     ordering = ['lastname','firstname', 'middlename'] 

class EmployeeAdmin(admin.ModelAdmin): 
    list_display = ('clocknumber','name') 
    fieldsets = [("Name", {"fields":(("lastname", "firstname", "middlename"), "clocknumber")}), 
     ] 

admin.site.register(Employee, EmployeeAdmin) 

अंत में मुझे लगता है कि मुझे लगता है कि मुझे फ़ील्ड के मूल्य स्ट्रिंग के रूप में प्राप्त करना है। मुझे जो त्रुटि मिल रही है वह value_to_string() takes exactly 2 arguments (1 given) है। स्ट्रिंग का मान self, obj चाहता है। मुझे यकीन नहीं है कि obj का अर्थ क्या है।

ऐसा करने का एक आसान तरीका होना चाहिए, मुझे यकीन है कि मैं ऐसा करने वाला पहला व्यक्ति नहीं हूं।

संपादित करें: यह मेरा कोड डैनियल के उत्तर में संशोधित है। मुझे जो त्रुटि मिलती है वह है:

django.core.exceptions.ImproperlyConfigured: 
    EmployeeAdmin.list_display[1], 'name' is not a callable or an 
    attribute of 'EmployeeAdmin' of found in the model 'Employee'. 


from django.db import models 
from django.contrib import admin 

class Employee(models.Model): 
    lastname = models.CharField("Last", max_length=64) 
    firstname = models.CharField("First", max_length=64) 
    middlename = models.CharField("Middle", max_length=64) 
    clocknumber = models.CharField(max_length=16) 

    @property 
    def name(self): 
     return ''.join(
      [self.lastname,' ,', self.firstname, ' ', self.middlename]) 

    class Meta: 
     ordering = ['lastname','firstname', 'middlename'] 

class EmployeeAdmin(admin.ModelAdmin): 
    list_display = ('clocknumber','name') 
    fieldsets = [("Name", {"fields":(("lastname", "firstname", "middlename"), "clocknumber")}), 
] 

admin.site.register(Employee, EmployeeAdmin) 
+1

संभव डुप्लिकेट [Django मॉडल: फ़ील्ड मान अन्य फ़ील्ड की गणना है] (http://stackoverflow.com/questions/11465293/django-model-field-value-is-calculation-of-other-fileds) – Anto

उत्तर

28

ठीक है ... डैनियल रोज़मन का जवाब ऐसा लगता था जैसे इसे काम करना चाहिए था। जैसा कि हमेशा होता है, आप पर प्रश्न पोस्ट करने के बाद जो पाते हैं उसे ढूंढते हैं।

django 1.5 docs I found this example से जो बॉक्स के ठीक बाहर काम करता था। मदद के लिए आप सबका शुक्रिया। ,

from django.db import models 
from django.contrib import admin 

class Employee(models.Model): 
    lastname = models.CharField("Last", max_length=64) 
    firstname = models.CharField("First", max_length=64) 
    middlename = models.CharField("Middle", max_length=64) 
    clocknumber = models.CharField(max_length=16) 

    def _get_full_name(self): 
     "Returns the person's full name." 
     return '%s, %s %s' % (self.lastname, self.firstname, self.middlename) 
    full_name = property(_get_full_name) 


    class Meta: 
     ordering = ['lastname','firstname', 'middlename'] 

class EmployeeAdmin(admin.ModelAdmin): 
    list_display = ('clocknumber','full_name') 
    fieldsets = [("Name", {"fields":(("lastname", "firstname", "middlename"), "clocknumber")}), 
] 

admin.site.register(Employee, EmployeeAdmin) 
44

ऐसा कुछ नहीं है जो आप किसी क्षेत्र के रूप में करते हैं। यहां तक ​​कि अगर वह वाक्यविन्यास काम करता है, तो यह केवल तभी मूल्य प्रदान करेगा जब वर्ग परिभाषित किया गया था, न कि जब आप इसे एक्सेस करते हैं। आपको इसे एक विधि के रूप में करना चाहिए, और आप @property सजावट का उपयोग सामान्य विशेषता की तरह दिखने के लिए कर सकते हैं।

@property 
def name(self): 
    return ''.join(
     [self.lastname,' ,', self.firstname, ' ', self.middlename]) 

self.lastname आदि के रूप में सिर्फ अपने मूल्यों दिखाई देगा, इसलिए उन्हें बदलने के लिए किसी अन्य विधि कॉल करने की कोई जरूरत नहीं।

+0

मुझे लगता है कि यह कर्मचारी मॉडल में रखा गया है ... जिसने मुझे एक त्रुटि दी। क्या वह विधि कर्मचारी एडमिन क्लास में जानी चाहिए? मॉडल में – cstrutton

+0

नहीं। क्या त्रुटि है? –

+0

ऐसा करने का यही तरीका है। +1 – Matthias

6

डैनियल Roseman के समाधान परिकलित क्षेत्र एक Model की एक विशेषता बनाता है लेकिन यह does not make it accessible via QuerySet methods (जैसे all(), .values()।।):

यहाँ कोड है कि काम किया है। ऐसा इसलिए है क्योंकि QuerySet विधियों call the database directly, django Model को बाधित करते हैं।

चूंकि क्वेरीज़ सीधे डेटाबेस तक पहुंचते हैं, तो समाधान Manager की .get_queryset() विधि को अपने गणना क्षेत्र को जोड़कर ओवरराइड करना है। गणना की गई फ़ील्ड .annotate() का उपयोग करके बनाई गई है। अंत में, आप objects प्रबंधक को अपने Model में अपने नए Manager पर सेट करें।

मॉडल:

यहाँ कुछ इस प्रदर्शन कोड है।py

from django.db.models.functions import Value, Concat 
from django.db import Model 

class InvoiceManager(models.Manager): 
    """QuerySet manager for Invoice class to add non-database fields. 

    A @property in the model cannot be used because QuerySets (eg. return 
    value from .all()) are directly tied to the database Fields - 
    this does not include @property attributes.""" 

    def get_queryset(self): 
     """Overrides the models.Manager method""" 
     qs = super(InvoiceManager, self).get_queryset().annotate(link=Concat(Value("<a href='#'>"), 'id', Value('</a>'))) 
     return qs 

class Invoice(models.Model): 
    # fields 

    # Overridden objects manager 
    objects = InvoiceManager() 

अब, आप .values() या .all() कॉल और के रूप में Manager में घोषित नव गणना की link विशेषता उपयोग करने में सक्षम हो जाएगा।

other functions.annotate() में F() में उपयोग करना भी संभव होगा।

मेरा मानना ​​है कि विशेषता अभी भी object._meta.get_fields() में उपलब्ध नहीं होगा। मेरा मानना ​​है कि आप इसे यहां जोड़ सकते हैं, लेकिन मैंने यह नहीं खोजा है कि - कोई भी संपादन/टिप्पणियां सहायक होंगी।

+0

बस मेरे अपने को समझने के लिए, क्यों डीईएफ़ __ (स्वयं) __str नहीं है? यह सही हिस्सा ओपी संदर्भित (Django 1.10 संस्करण) https://docs.djangoproject.com/en/1.10/topics/db/models/#model-methods के तहत किए गए दस्तावेज़ों में बताया गया है। क्या ऐसा है कि आप किसी ऑब्जेक्ट को कॉल करने या नामकरण करने के एक से अधिक तरीके से हो सकते हैं? वैकल्पिक रूप से, क्या आप def__str2__ वापस self.othername जैसे कुछ कर सकते हैं? –

+0

@ MalikA.Rumi 'self.whatever' केवल मॉडल का एक उदाहरण के लिए लागू होगी, लेकिन क्वेरीसमूहों पर लागू नहीं होगा (जो है, सभी उदाहरणों' सब के सब द्वारा दिया() 'या' .filter() ') । 'स्वयं। जो कुछ भी एक उदाहरण को संदर्भित करता है और क्वेरीसेट्स के लिए मौजूद नहीं होगा। –

+0

धन्यवाद एलेक्स, यह मेरे लिए Django 1.11 के साथ काम करता है। इसके अलावा मुझे व्यवस्थापक में इन एनोटेटेड फ़ील्ड्स का उपयोग करने की आवश्यकता थी लेकिन संभव नहीं था, लेकिन एक वर्कअराउंड [यहां] (https://stackoverflow.com/a/26618982/503743) इसे व्यवस्थापक इंटरफेस के साथ भी उपयोग करने की अनुमति देता है। – Mrdev

1

इस मामले में आप केवल आप बेहतर str() या यूनिकोड() वर्ग की विधि अधिभावी विचार करने के लिए हो सकता है के रूप में यह उल्लेख किया गया है व्यवस्थापक साइट और इस तरह के मुद्दों में प्रतिनिधित्व के लिए क्षेत्र का उपयोग करने जा रहे हैं, Django प्रलेखन here में:

class Employee(models.Model): 
    # fields definitions 
    def __str__(self): 
     return self.lastname + ' ,' + self.firstname + ' ' + self.middlename 
0

मैं हाल ही में एक पुस्तकालय है कि समस्या आप काफी आसानी हो रही हो, समाधान हो सकता है पर काम किया।

https://github.com/brechin/django-computed-property

कि स्थापित करें, INSTALLED_APPS को जोड़ने और फिर

class Employee(models.Model): 
    ... 
    name = computed_property.ComputedCharField(max_length=3 * 64, compute_from='full_name') 

    @property 
    def full_name(self): 
     return '{LAST}, {FIRST} {MIDDLE}'.format(LAST=self.lastname, FIRST=self.firstname, MIDDLE=self.middlename') 
की