2011-04-27 34 views
12

Vì vậy, mục tiêu của tôi là có thể lọc bộ truy vấn ModelChoiceField trong ModelForm của tôi để chỉ bao gồm Địa điểm mà request.user đã tạo.Gửi đối tượng request.user đến ModelForm từ chế độ xem chung dựa trên lớp ở Django

My ModelForm chỉ đơn giản là:

class PlaceEventForm(models.ModelForm): 
    class Meta: 
     model = Event 

Tôi muốn để có thể thêm một cái gì đó như:

def __init__(self, *args, **kwargs): 
    super(PlaceEventForm, self).__init__(*args, **kwargs) 
    self.fields['place'].queryset = Place.objects.filter(created_by=request.user) 

Tuy nhiên, tôi dường như không thể tìm thấy một cách để truy cập theo yêu cầu trong ModelForm.

My View là như vậy:

class PlaceEventFormView(CreateView): 
    form_class = PlaceEventForm 
    template_name = 'events/event_create.html' 

    @method_decorator(login_required) 
    def dispatch(self, *args, **kwargs): 
     return super(PlaceEventFormView, self).dispatch(*args, **kwargs) 

Tôi không chắc chắn nếu điều này thậm chí còn gần với những gì tôi nên làm, nhưng tôi đã cố gắng:

def get_form_kwargs(self): 
    kwargs = super(PlaceEventFormView, self).get_form_kwargs() 
    kwargs.update({'place_user': self.request.user}) 
    return kwargs 

Nhưng tôi đã nhận lỗi: init() có đối số từ khóa không mong muốn 'place_user'

Bất kỳ ý tưởng nào về vấn đề này? Hoặc bất cứ ai có thể nghĩ ra một cách để lọc ModelChoiceField của tôi trong xem mà không cần phải vượt qua yêu cầu của tôi để ModelForm?

Trả lời

20

Bạn cần phải bật chìa khóa user từ kwargs trong PlaceEventForm.__init__() phương pháp, để ngăn chặn nó từ sẽ ModelForm.__init__() phương pháp:

views.py:

class PlaceEventFormView(CreateView): 
    form_class = PlaceEventForm 
    template_name = 'events/event_create.html' 

    @method_decorator(login_required) 
    def dispatch(self, *args, **kwargs): 
     return super(PlaceEventFormView, self).dispatch(*args, **kwargs) 

    def get_form_kwargs(self): 
     kwargs = super(PlaceEventFormView, self).get_form_kwargs() 
     kwargs.update({'place_user': self.request.user}) 
     return kwargs 

forms.py:

class PlaceEventForm(models.ModelForm): 
    class Meta: 
     model = Event 

    def __init__(self, *args, **kwargs): 
     user = kwargs.pop('place_user') 
     # now kwargs doesn't contain 'place_user', so we can safely pass it to the base class method 
     super(PlaceEventForm, self).__init__(*args, **kwargs) 
     self.fields['place'].queryset = Place.objects.filter(created_by=user) 
+0

Cảm ơn rất nhiều! Hoạt động hoàn hảo. – Brian

+0

Gặp sự cố khi hiểu cách bạn thực hiện việc này. –

+0

Tôi đã làm ví dụ hoàn chỉnh, cho tôi biết nếu nó vẫn chưa rõ ràng –

1

Tôi đang sử dụng iPhone nhưng thực hiện việc này:

def get_form(self, form_class): 
    form = super(MyView, self).get_form(form_class) 
    form.fields['place'].querset = Place.... 
    return form 

Chà thật khó! Không hỗ trợ indention!

0

Để cập nhật câu trả lời của Yuji cho Django 1.10+ (bao gồm cả Django 2.0+), xem ví dụ bên dưới (lưu ý chữ ký phương thức được cập nhật). Cách tiếp cận được đề xuất của Yuji giữ truy vấn trong khung nhìn cùng với logic nghiệp vụ khác và giúp giữ cho bất kỳ lớp biểu mẫu nào mở rộng models.ModelForm rõ ràng và đơn giản.

def get_form(self, form_class=None): 
    if form_class is None: 
     form_class = self.get_form_class() 
    form = super(MyView, self).get_form() 
    form.fields['place'].queryset = Place.objects.filter(created_by=self.request.user) 
    return form 

ngắn:

def get_form(self, form_class=None): 
    form = super(MyView, self).get_form(form_class) 
    form.fields['place'].queryset = Place.objects.filter(created_by=self.request.user) 
    return form 
Các vấn đề liên quan