2010-04-05 47 views
7

Tôi đang cố gắng sử dụng inlineformset_factory để tạo một bộ định dạng. Mô hình của tôi được định nghĩa là:Bộ lọc truy vấn trong Django inlineformset_factory

class Measurement(models.Model): 
    subject = models.ForeignKey(Subject) 
    experiment = models.ForeignKey(Experiment) 
    assay = models.ForeignKey(Assay) 
    values = models.CommaSeparatedIntegerField(blank=True, null=True) 

class Experiment(models.Model): 
    date = models.DateField() 
    notes = models.TextField(max_length = 500, blank=True) 
    subjects= models.ManyToManyField(Subject) 

theo quan điểm của tôi, tôi có:

def add_measurement(request, experiment_id): 
    experiment = get_object_or_404(Experiment, pk=experiment_id) 
    MeasurementFormSet = inlineformset_factory(Experiment, Measurement, extra=10, exclude=('experiment')) 
    if request.method == 'POST': 
     formset = MeasurementFormSet(request.POST,instance=experiment) 
     if formset.is_valid(): 
      formset.save() 
      return HttpResponseRedirect(experiment.get_absolute_url()) 
    else: 
     formset = MeasurementFormSet(instance=experiment) 
    return render_to_response("data_entry_form.html", {"formset": formset, "experiment": experiment }, context_instance=RequestContext(request)) 

nhưng tôi muốn để hạn chế lĩnh vực Measurement.subject để chỉ các đối tượng quy định tại các queryset Experiment.subjects. Tôi đã thử một vài cách khác nhau để làm điều này nhưng tôi là một chút không chắc chắn cách tốt nhất để thực hiện điều này là gì. Tôi đã cố gắng để vượt qua lớp BaseInlineFormset với một queryset mới, nhưng không thể tìm ra cách để truyền một cách chính xác tham số thử nghiệm.

câu trả lời Cập nhật (Tôi cũng bao gồm các thông tin từ đây như một cách để vượt qua các tham số cho formset link):

views.py

def add_measurement(request, experiment_id):  
    experiment = get_object_or_404(Experiment, pk=experiment_id)  
    MeasurementFormSet = inlineformset_factory(Experiment, Measurement, extra=10, can_delete=True, form=MeasurementForm)  
    MeasurementFormSet.form = staticmethod(curry(MeasurementForm, experiment=experiment)) 
    if request.method == 'POST': 
     formset = MeasurementFormSet(request.POST)  
     if formset.is_valid(): 
     formset.save() 
     return HttpResponseRedirect(experiment.get_absolute_url())  
    else: 
     formset = MeasurementFormSet() 
     return render_to_response("data_entry_form.html", {"formset": formset, "experiment": experiment }, context_instance=RequestContext(request)) 

forms.py

class MeasurementForm(ModelForm): 
    class Meta: 
     model = Measurement 
    def __init__(self, *args, **kwargs): 
     experiment = kwargs.pop('experiment') 
     super(MeasurementForm, self).__init__(*args, **kwargs) 
     self.fields["subject"].queryset = Subject.objects.filter(experiment=experiment) 
+0

Tôi chưa bao giờ nghe nói về cà ri() bằng Python trước đây, nó chắc chắn không được tích hợp sẵn. EDIT: ... Ahh .. Tôi vừa nhận thấy bài đăng được liên kết: từ django.utils chức năng nhập khẩu cà ri – Rich

+0

Điều này vẫn còn làm việc trong Django 1,5? Tôi nhận được lỗi sau: __init __() nhận được đối số từ khóa không mong muốn 'empty_permitted' – Puzzled79

Trả lời

3

(chỉnh sửa: không đọc các khối mã đúng cách, đây phải là giải pháp cho vấn đề của bạn):

Tôi tin rằng bạn cần: http://docs.djangoproject.com/en/dev/ref/forms/fields/#modelchoicefield

Forms.py:

class MeasurementForm(ModelForm): 
subject = forms.ModelChoiceField(queryset = Expirement.objects.all()) 
class Meta: 
    model = Measurement 

Views.py:

inlineformset_factory(
    Experiment, Measurement, extra=10, 
    exclude=('experiment'), form=MeasurementForm 
) 

Binding để formset được thực hiện sử dụng tham số hình thức.

+0

Tôi đã thử điều này nhưng không có nhiều may mắn. Mục đích của phần tử lọc và tiền tố là gì? – Dave

+0

Đã chỉnh sửa câu trả lời của tôi ngày hôm qua, modelchoicefield nên có các thành phần cho một giải pháp. –

+0

Tôi đã thay đổi mã của mình (xem phần bổ sung trong câu hỏi) nhưng bây giờ lỗi là khi lưu. Lỗi hiện tại là "Không thể chỉ định" <Đo lường: Đối tượng đo lường "": "Measurement.experiment" phải là một ví dụ "Thử nghiệm". " – Dave

1

Tôi đã gặp phải vấn đề tương tự (khởi tạo biểu mẫu nội tuyến với một giá trị có thể có giới hạn) và câu trả lời Cập nhật hoạt động tốt. Cảm ơn vì điều đó. Dù sao, có cái gì đó có thể được thực hiện tốt hơn tôi nghĩ, nhưng tôi không có đầu mối làm thế nào để làm cho nó thực hiện. Các vấn đề mới trong giải pháp đó là bạn nhấn cơ sở dữ liệu trong mỗi inlineform: thay vì sử dụng queryset nhau trong tất cả các lĩnh vực tương tự, tính toán lại mỗi lần ở dòng này:

self.fields["subject"].queryset = Subject.objects.filter(experiment=experiment) 

Tôi có ngay trong vấn đề này hoặc có một số ma thuật lười biếng-django đằng sau mui xe? Nếu tôi đúng, làm thế nào tôi có thể tránh (có thể hàng trăm) số truy cập vào DB? Chúc mừng, Pedro

+0

Để tránh các lần truy cập đến DB, chỉ cần bao quanh bộ lọc truy vấn sử dụng thủ thuật của []ukaszKorzybski] (http://stackoverflow.com/a/2108902/623735) - 'if not hasattr (self, '_queryset'):' – hobs

Các vấn đề liên quan