2010-09-09 10 views
13

पृष्ठभूमिप्रति-वस्तु अनुमतियाँ जोड़ने व्यवस्थापक

मैं एक छुट्टी किराये की साइट के लिए एक Django एप्लिकेशन विकसित करने कर रहा हूँ django करने के लिए। इसमें दो प्रकार के उपयोगकर्ता, किराएदारों और संपत्ति प्रबंधक होंगे।

मैं संपत्ति प्रबंधकों को django व्यवस्थापक में अपने किराये की संपत्तियों का प्रबंधन करने में सक्षम होना चाहता हूं। हालांकि, वे केवल अपनी संपत्ति का प्रबंधन करने में सक्षम होना चाहिए।

मुझे एहसास है कि डिफ़ॉल्ट django व्यवस्थापक इसका समर्थन नहीं करता है। मैं सोच रहा हूं कि इस कार्यक्षमता को जोड़ने में कितना परेशानी होगी, और यदि यह संभव है, तो इसे संभालने का सबसे अच्छा तरीका क्या है।


लक्ष्य

आदर्श रूप में, मैं यह कुछ इस तरह काम कर चित्र:

auth पहले से ही इस तरह की अनुमति देता है अनुमतियाँ:

 
vacation | rental | Can add rental 
vacation | rental | Can change rental 
vacation | rental | Can delete rental 

मैं करने के लिए इस बदलना चाहते हैं कुछ ऐसा:

 
vacation | rental | Can add any rental 
vacation | rental | Can change any rental 
vacation | rental | Can delete any rental 
vacation | rental | Can add own rental 
vacation | rental | Can change own rental 
vacation | rental | Can delete own rental 

संभव समाधान

ढांचा कैसे तय होगा किराए पर लेने (या जो भी) उपयोगकर्ता के अंतर्गत आता है तो क्या होगा? मुझे लगता है कि यह vacation.Rental कक्षा को देखने के लिए जांचता है कि क्या यह ForeignKey से auth.User (संभवतः कुछ विशेष नाम, जैसे 'स्वामी') है।

  • एक नई vacation.Rental बनाने पर, ForeignKey फ़ील्ड का मान वर्तमान उपयोगकर्ता के आईडी के लिए मजबूर हो जाएगा। ForeignKey फ़ील्ड फॉर्म पर प्रदर्शित नहीं होगा।

  • लिस्टिंग किराया पर, वर्तमान उपयोगकर्ता से मेल खाने वाले ForeignKey के साथ केवल किराए पर प्रदर्शित किया जाएगा।

  • किराया बदलने पर, वर्तमान उपयोगकर्ता से मेल खाने वाले ForeignKey के साथ केवल किराए पर प्रदर्शित किया जाएगा। ForeignKey फ़ील्ड फॉर्म पर प्रदर्शित नहीं होगा।

बेशक

, इस, एक उपयुक्त ForeignKey क्षेत्र होने के लिए किसी भी मॉडल के लिए काम करने के लिए ही नहीं, हमारे vacation.Rental मॉडल सक्षम होना चाहिए।

क्या यह ध्वनि अभी तक व्यवहार्य है, या मुझे एक अलग दिशा में जाना चाहिए?


जटिलताओं

अब, यहाँ मुश्किल हिस्सा है; मुझे यकीन नहीं है कि इसे कैसे संभालें। मान लें कि Rental में कई "RentalPhotos" हो सकते हैं। RentalPhoto में ForeignKey से Rental है।उपयोगकर्ता अपने स्वयं के किराये में फोटो जोड़ने में सक्षम होना चाहिए। हालांकि, तस्वीरों में उपयोगकर्ता ForeignKey नहीं है, इसलिए तस्वीर का मालिक कौन है यह जानने का कोई तरीका नहीं है।

क्या यह ForeignKey के बाद फ्रेमवर्क में कुछ चालबाजी द्वारा हल किया जा सकता है जब तक कोई ऑब्जेक्ट ForeignKey उपयोगकर्ता के साथ नहीं मिलता है? या क्या मुझे आसान तरीका निकालना चाहिए और RentalPhoto (और अन्य सभी 'संबंधित' से Rental) को ForeignKey उचित auth.User पर देना चाहिए? दूसरा दृष्टिकोण अनियंत्रित अनावश्यकता को आमंत्रित करेगा, पहले शायद अनावश्यक प्रसंस्करण ओवरहेड की आवश्यकता होगी ...

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

उत्तर

22

मैं बस प्रत्येक मॉडल is_owned_by(user) पर एक विधि जोड़ता हूं, और यह तय करने के लिए मॉडल तक है कि यह उस उपयोगकर्ता के स्वामित्व में है या नहीं। अधिकांश मामलों में is_owned_by आधार मॉडल वर्ग में एक सामान्य कार्य हो सकता है और आप इसे विशेष मामलों में बदल सकते हैं। जैसे

class RentalPhoto(BaseModel): 
    def is_owned_by(self, user): 
     return self.rental.is_owned_by(user) 

यह सामान्य है और स्पष्ट है कि आपके पास पूर्ण नियंत्रण होगा कि चीजें कैसे व्यवहार करती हैं।

नई अनुमति जोड़ने के लिए आप इसे अपने मॉडल में जोड़ सकते हैं उदा।

class Rental(models.Model): 
    # ... 
    class Meta: 
     permissions = (
      ("can_edit_any", "Can edit any rentals"), 
     ) 

मैं बजाय any और own के लिए दो अनुमति जोड़ने के बारे में सोच, आप केवल own अनुमति जोड़ना चाहिए, इसलिए प्रत्येक वस्तु पहले से ही can_edit जो आप उपयोगकर्ता के रूप में इलाज कर सकते हैं है केवल अपने ऑब्जेक्ट को संपादित कर सकते हैं और उपयोगकर्ता की अनुमति can_edit_any है अगर केवल उन्हें सभी

संपादित करने की अनुमति है, इसका उपयोग करके हम कस्टम बैकएंड जोड़कर ऑथ बढ़ा सकते हैं

class PerObjectBackend(ModelBackend): 

    def has_perm(self, user_obj, perm, obj=None): 
     allowed = ModelBackend.has_perm(self, user_obj, perm) 
     if perm.find('any') >=0 : 
      return allowed 

     if perm.find('edit') >=0 or perm.find('delete') >=0: 
      if obj is None: 
       raise Exception("Perm '%s' needs an object"%perm) 
      if not obj.is_owned_by(user_obj): 
       return False 

     return allowed 

यह एक बहुत तेज़ implemenation है, वास्तव में आप अगर यह की जरूरत है और वस्तु या नहीं जैसे जांच करने के लिए अनुमति की वस्तुओं का विस्तार कर सकते बजाय कच्चे स्ट्रिंग खोज करने का permission.is_per_object लेकिन यदि आप मानक नाम

+0

धन्यवाद, अनुराग; यह उतना सामान्य नहीं है जितना मैं चाहता हूं लेकिन मैं इसे मानूंगा। मैं इसे 'auth' में कैसे बांध सकता हूं, इसलिए मेरी नई अनुमतियां सूची में दिखाई देती हैं? –

+0

@no संपादन देखें। –

1

इस में कुछ प्रवंचना ढांचे द्वारा हल किया जा सकता है, निम्नलिखित ForeignKeys जब तक एक वस्तु उपयोगकर्ता के लिए एक ForeignKey साथ पाया जाता है?

मैं नहीं दिख रहा है जहां प्रवंचना necessairy: RentalPhoto -> किराये -> उपयोगकर्ता तो एक विशेष RentalPhoto आप उदाहरण में कुछ इस तरह कहेंगे के लिए उपयोगकर्ता पाने के लिए:

photo.rental.user 

एक कदम में कई संबंधों के बाद गैर-चालबाजी के रूप में माना जा सकता है।

+0

कि इस विशेष मामले के लिए काम करेंगे, लेकिन मैं एक सामान्य तरीके से करना चाहते हैं - "बेशक, यह किसी भी मॉडल होने के लिए काम करने के लिए सक्षम होना चाहिए उपयुक्त 'विदेशीकी' फ़ील्ड, न केवल हमारी 'छुट्टी'। मानसिक '[और संबंधित] मॉडल [ओं]। " –

+0

अधिक सामान्य होने के संभावित तरीकों के दर्जनों की तरह हैं। जैसे एक मॉडल है। औपचारिक जो फ़ील्ड के मालिक को परिभाषित करता है और इसे अपने मॉडल में विस्तारित करता है। –

+0

यह उत्तर बहुत उपयोगी नहीं है। यह अधिकांश प्रश्न अनुत्तरित छोड़ देता है। शायद मैंने सवाल समझाने का बुरा काम किया है? –

1

आप अपने खुद के अनुमति बैकएंड लागू करने के लिए नहीं करना चाहते हैं, मैं तुम्हें एक बहुत आसान में https://github.com/chrisglass/django-rulez उपयोग करने के लिए आप आप क्या चाहते हैं क्या करेंगे सुझाव है कि यह भी काम करना चाहिए मार्ग।

0

यह Django docs में है।

असल में आप अपने मॉडल के लिए कस्टम एडमिन क्लास बनाते हैं, और get_queryset विधि को परिभाषित करते हैं। आपके मामले में यह नीचे की तरह कुछ हो सकता है।सुपर उपयोगकर्ता सभी किराया देखेंगे, जबकि मालिक केवल उसके ही।

class RentalAdmin(admin.ModelAdmin): 
    def get_queryset(self, request): 
     qs = super(RentalAdmin, self).get_queryset(request) 
     if request.user.is_superuser: 
      return qs 
     return qs.filter(owner=request.user) 

यहाँ एक और संभव नेतृत्व है: https://code.djangoproject.com/wiki/RowLevelPermissions

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