2012-03-16 19 views
6

मुझे किसी फ़ॉर्मेट में चयन करने योग्य विकल्पों को सीमित करने में समस्याएं आ रही हैं। मेरे पास निम्नलिखित मॉडल हैं: कर्मचारी, विभाग, परियोजना, परियोजना प्रकार, सदस्यता, और भूमिका। एक कर्मचारी फॉर्मेट में किसी दिए गए विभाग परियोजना के लिए जो भूमिका निभाता है उसे जोड़/हटा सकता है, फॉर्म को चुनिंदा परियोजनाओं को केवल उस विभाग से संबंधित होना चाहिए जो कर्मचारी संबंधित है।django: फ़ॉर्मेट में फ़ील्ड विकल्पों को कैसे सीमित करें?

मॉडल:

class Department(models.Model): 
    name = models.CharField(max_length=20) 
    def __unicode__(self): 
    return self.name 

class Employee(models.Model): 
    fname = models.CharField(max_length=15) 
    department = models.ForeignKey(Department) 
    def __unicode__(self): 
     return self.fname 

class Projecttype(models.Model): 
    name = models.CharField(max_length=20) 
    def __unicode__(self): 
     return self.name 

class Project(models.Model): 
    projecttype = models.ForeignKey(Projecttype) 
    department = models.ForeignKey(Department) 
    members = models.ManyToManyField(Employee, through='Membership') 
    def __unicode__(self): 
     return "%s > %s" % (self.department, self.projecttype) 

class Role(models.Model): 
    name = models.CharField(max_length=20) 
    def __unicode__(self): 
     return self.name 

class Membership(models.Model): 
    project = models.ForeignKey(Project, null=True) 
    department = models.ForeignKey(Department) 
    employee = models.ForeignKey(Employee) 
    role = models.ManyToManyField(Role, blank=True, null=True) 
    class Meta: 
     unique_together = (("project", "employee",),) 

देखें:

def employee_edit(request, employee_id): 
    i = get_object_or_404(Employee, pk=employee_id) 
    MembershipFormSet = modelformset_factory(Membership, exclude=('department', 'employee'),) 
    f = MembershipFormSet(queryset=Membership.objects.filter(employee=i),) 
    return render_to_response('gcs/edit.html', {'item': i, 'formset': f, }, context_instance=RequestContext(request)) 

अभी एक यूरोपीय संघ के किसी भी विभागों परियोजना के लिए खेलने के लिए एक भूमिका का चयन कर सकते हैं। यह इस तरह से कार्य करे, तो:

परियोजना विकल्प:

Projects.objects.all() 

मैं कुछ इस तरह के साथ परियोजनाओं को सीमित करना चाहते: LIMIT परियोजना CHOCIES के लिए:

Projects.objects.filter(department=i.department) 
+0

[यह ढेर अतिप्रवाह सवाल] (http://stackoverflow.com/questions/622982/django-passing-custom-form-parameters-to-formset) काफी है समान। काम करने वाले दो दृष्टिकोण हैं। 1) एक ऐसा फॉर्म बनाएं जो कर्मचारी को '__init__' विधि में तर्क के रूप में लेता है और करी फ़ंक्शन का उपयोग करता है। 2) व्यू फ़ंक्शन में फॉर्म क्लास बनाएं।यदि आपको कहीं और फॉर्म का पुन: उपयोग करने की आवश्यकता नहीं है, तो मुझे दूसरा दृष्टिकोण आसान लगता है। – Alasdair

+0

नया पायथन के लिए, क्या आप फॉर्म क्लास को दृश्य में रूपांतरित करते हैं जैसे आप model.py में करेंगे? – thedeepfield

+0

मैंने अपनी टिप्पणी को नीचे दिए गए उत्तर के रूप में विस्तारित किया है। – Alasdair

उत्तर

7

यह Stack Overflow question काफी समान है। मुझे मैथ्यू के जवाब के दृष्टिकोण पसंद हैं, जहां आप एक ऐसे फ़ंक्शन में गतिशील रूप से फ़ॉर्म बनाते हैं जिसके पास कर्मचारी के पास बंद होने के माध्यम से पहुंच है। आपके मामले में, आप चाहते हैं कुछ की तरह:

from django.http import HttpResponseRedirect 

def make_membership_form(employee): 
    """ 
    Returns a Membership form for the given employee, 
    restricting the Project choices to those in the 
    employee's department. 
    """ 
    class MembershipForm(forms.ModelForm): 
     project = forms.ModelChoiceField(queryset=Projects.objects.filter(department=employee.department)) 
     class Meta: 
      model = Membership 
      excludes = ('department', 'employee',) 
    return MembershipForm 

def employee_edit(request, employee_id): 
    employee = get_object_or_404(Employee, pk=employee_id) 
    # generate a membership form for the given employee 
    MembershipForm = make_membership_form(employee) 
    MembershipFormSet = modelformset_factory(Membership, form=MembershipForm) 

    if request.method == "POST": 
     formset = MembershipFormSet(request.POST, queryset=Membership.objects.filter(employee=employee)) 
     if formset.is_valid(): 
      instances = formset.save(commit=False) 
       for member in instances: 
        member.employee = employee 
        member.department = employee.department 
        member.save() 
      formset.save_m2m() 
      # redirect after successful update 
      return HttpResponseRedirect("") 
    else: 
     formset = MembershipFormSet(queryset=Membership.objects.filter(employee=employee),) 
    return render_to_response('testdb/edit.html', {'item': employee, 'formset': formset, }, context_instance=RequestContext(request)) 
+0

कक्षा सदस्यता है मॉडल को देखने या मॉडल में होने का अनुमान है? – thedeepfield

+0

मुझे फंक्शन के बाहर 'वापसी' कहने में त्रुटि मिली है – thedeepfield

+0

प्रपत्र वास्तव में 'models.py' में नहीं हैं। बड़े Django ऐप्स में, आपके पास कभी-कभी 'form.py' मॉड्यूल होता है। इस मामले में, यदि आप चाहें तो 'view.py' में 'make_membership_form' फ़ंक्शन डाल सकते हैं। – Alasdair

3

संपादित

अरे । वह सब टाइपिंग क्योंकि मैं कोड के एक हिस्से को याद करता हूं;)। जैसा कि @ अलास्डेयर ने टिप्पणियों में उल्लेख किया है, आपने फॉर्म से department को बाहर कर दिया है, ताकि आप इसे Django से सीमित कर सकें। मैं अपना मूल जवाब छोड़ने जा रहा हूं, हालांकि, अगर यह किसी और की मदद कर सकता है।

अपनी परिस्थितियों के लिए, आप सभी की जरूरत है:

class MembershipForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(MembershipForm, self).__init__(*args, **kwargs) 
     self.fields['project'].queryset = self.fields['project'].queryset.filter(department_id=self.instance.department_id) 

और, तो:

MembershipFormSet = modelformset_factory(Membership, form=MembershipForm, exclude=('department', 'employee'),) 

(भावी पीढ़ी के लिए)

मूल उत्तर आप इस सीमित नहीं कर सकते Django, क्योंकि विभाग के लिए मूल्य बदलने योग्य है, और इस प्रकार परियोजनाओं की सूची अलग-अलग हो सकती है कि किस विशेष विभाग को मोम में चुना जाता है NT। फॉर्म को प्रमाणित करने के लिए, आपको सभी संभावित परियोजनाओं को खिलाना होगा जिन्हें Django को अनुमति दी जा सकती है, इसलिए आपका एकमात्र विकल्प AJAX है।

एक ऐसा दृश्य बनाएं जो एक विशेष विभाग के लिए परियोजनाओं से युक्त एक JSON प्रतिक्रिया वापस करेगा। की तर्ज पर कुछ:

from django.http import HttpResponse, HttpResponseBadRequest 
from django.shortcuts import get_list_or_404 
from django.utils import simplejson 

def ajax_department_projects(request): 
    department_id = request.GET.get('department_id') 
    if department_id is None: 
     return HttpResponseBadRequest() 

    project_qs = Project.objects.select_related('department', 'project_type') 
    projects = get_list_or_404(project_qs, department__id=department_id) 
    data = [] 
    for p in projects: 
     data.append({ 
      'id': p.id, 
      'name': unicode(p), 
     }) 

    return HttpResponse(simplejson.dumps(data), mimetype='application/json') 

फिर, इस दृश्य को लाने के लिए जावास्क्रिप्ट का एक सा बनाने के लिए जब भी विभाग सलेक्ट बॉक्स बदल गई है:

(function($){ 
    $(document).ready(function(){ 
     var $department = $('#id_department'); 
     var $project = $('#id_project'); 

     function updateProjectChoices(){ 
      var selected = $department.val(); 
      if (selected) { 
       $.getJSON('/path/to/ajax/view/', {department_id: selected}, function(data, jqXHR){ 
        var options = []; 
        for (var i=0; i<data.length; i++) { 
         output = '<option value="'+data[i].id+'"'; 
         if ($project.val() == data[i].id) { 
          output += ' selected="selected"'; 
         } 
         output += '>'+data[i].name+'</option>'; 
         options.push(output); 
        } 
        $project.html(options.join('')); 
       }); 
      } 
     } 

     updateProjectChoices(); 
     $project.change(updateProjectChoices); 
    }); 
})(django.jQuery); 
+0

'विभाग' बदलने योग्य नहीं है - नोट 'बहिष्कृत करें = (' विभाग ',' कर्मचारी '),)'। – Alasdair

+0

ओएमजी धन्यवाद, मैं इस मुद्दे पर एक हफ्ते तक फंस गया हूं। मैंने एक समान जवाब को चारों ओर फेंक दिया लेकिन कभी भी पूरी तरह से समझ नहीं पाया कि क्या हो रहा है। क्या आप कृपया मुझे बता सकते हैं कि इस कोडिंग विज़ार्ड का क्या अर्थ है? संदर्भ? – thedeepfield

+0

इसके अलावा, मेरी सदस्यता में एक नई सदस्यता प्रविष्टि बनाने के लिए एक अतिरिक्त खाली फॉर्म है। हालांकि इस नए रूप में प्रोजेक्ट फ़ील्ड में कोई विकल्प नहीं है ... मेरे विकल्प अब क्यों गायब हैं? – thedeepfield

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