2009-10-12 24 views
11

कस्टम प्रपत्र में, कोई मॉडल के फ़ील्ड की विशिष्टता को कैसे मान्य करता है (यानी, unique=True सेट है)?मॉडलफॉर्म का उपयोग किये बिना एक अद्वितीय = सही फ़ील्ड को कैसे सत्यापित/साफ() करें?

मुझे पता है कि Django के ModelForm स्वचालित रूप से एक validate_unique() समारोह है कि BaseModelForm के clean() विधि के भीतर कहा जाता है करता है - तो, ​​जब ModelForm का उपयोग कर, यह सही ढंग से नियंत्रित किया जाएगा (के रूप में यह व्यवस्थापक में है)।

हालांकि, मैं खरोंच से अपना खुद का फॉर्म बना रहा हूं और आश्चर्यचकित हूं कि मैं इसे स्वयं कैसे संभालने के बारे में जा सकता हूं? मुझे लगता है कि मेरी सबसे बड़ी बाधा जानना है जो वस्तु प्रपत्र जब डेटा साफ किया जा रहा है से जुड़ा हुआ है ...

कुछ कोड:

class UserProfile(CreatedModifiedModel): 
    user   = models.ForeignKey(User, unique=True) 
    display_name = models.CharField('Display Name',max_length=30, 
         blank=True,unique=True) 

class EditUserProfileForm(forms.Form): 
    display_name = forms.CharField(required=False,max_length=30) 

    # "notifications" are created from a different model, not the UserProfile 
    notifications = forms.MultipleChoiceField(
         label="Email Notifications", 
         required=False, 
         widget=forms.CheckboxSelectMultiple,) 

    def clean_display_name(self): 
     # how do I run my own validate_unique() on this form? 
     # how do I know which UserProfile object I am working with? 

    # more code follows, including the __init__ which sets up the notifications 
+1

क्या कोई कारण है कि आप मॉडलफॉर्म के बजाय कस्टम फॉर्म बना रहे हैं? – tghw

+0

मैंने "नोटिफिकेशन" फ़ील्ड दिखाने के लिए कोड अपडेट किया है, मुझे एक अलग ऐप से चाहिए, लेकिन उसी एडिट यूज़रप्रोफाइलफॉर्म पर संभाला गया है ... उम्मीद है कि यह समझ में आता है। मुझे नहीं लगता कि मैं कई मॉडल स्रोतों से मॉडलफॉर्म बना सकता हूं ... – thornomad

उत्तर

15

अनोखा सत्यापन पूरी तरह से सही करने के लिए मुश्किल है, इसलिए मैं करूंगा वैसे भी एक ModelForm उपयोग करने की अनुशंसा:

class EditUserProfileForm(forms.ModelForm): 
    # "notifications" are created from a different model, not the UserProfile 
    notifications = forms.MultipleChoiceField(
         label="Email Notifications", 
         required=False, 
         widget=forms.CheckboxSelectMultiple,) 

    class Meta: 
     model = UserProfile 
     fields = ('display_name',) 

अनेक मॉडल से एक फार्म बनाना आसान नहीं है, लेकिन इस मामले में आप सिर्फ ModelForm पर notifications क्षेत्र जोड़ने और इसे .cleaned_data हमेशा की तरह से बाहर निकलने कर सकते हैं:

# view 
if request.method == 'POST': 
    form = EditUserProfileForm(request.POST, instance=user_profile) 
    if form.is_valid(): 
     user_profile = form.save() 
     notifications = form.cleaned_data['notifications'] 
     # Do something with notifications. 

कि कैसे मैं यह कर सकता है, लेकिन आप अपने आप को अद्वितीय को मान्य करने पर सेट कर रहे हैं, तो आप हमेशा की तरह कुछ कर सकते हैं:

def clean_display_name(self): 
    display_name = self.cleaned_data['display_name'] 
    if UserProfile.objects.filter(display_name=display_name).count() > 0: 
     raise ValidationError('This display name is already in use.') 
    return display_name 

मैं यहाँ देख दो समस्याएं हैं। सबसे पहले, आप समवर्ती मुद्दों में भाग ले सकते हैं, जहां दो लोग एक ही नाम जमा करते हैं, दोनों अद्वितीय चेक पास करते हैं, लेकिन फिर किसी को डीबी त्रुटि मिलती है। दूसरी समस्या यह है कि आप उपयोगकर्ता प्रोफ़ाइल को संपादित नहीं कर सकते हैं क्योंकि आपके पास खोज से बाहर निकलने के लिए कोई आईडी नहीं है। आप अपने __init__ में संग्रहीत और फिर सफाई में इसका उपयोग करना होगा:

def __init__(self, *args, **kwargs): 
    ... 
    if 'instance' in kwargs: 
     self.id = kwargs['instance'].id 
    ... 

def clean_display_name(self): 
    display_name = self.cleaned_data['display_name'] 
    qs = UserProfile.objects.filter(display_name=display_name) 
    if self.id: 
     qs = qs.exclude(pk=self.id) 
    if qs.count() > 0: 
     raise ValidationError('This display name is already in use.') 
    return display_name 

लेकिन उस बिंदु पर आप सिर्फ ModelForms में तर्क डुप्लिकेट बना रहे हैं।

+1

अरे - इसके लिए धन्यवाद। मुझे मॉडलफॉर्म में फ़ील्ड जोड़ने के बारे में निश्चित नहीं था जो मॉडल के अनुरूप नहीं है ... लेकिन मैं इसे स्टार्टर्स के लिए आज़मा दूंगा। अगर मुझे समस्याएं वापस रिपोर्ट करेंगी। – thornomad

+0

tghw धन्यवाद भाई, महान जवाब – PyDroid

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

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