2012-02-18 35 views
9

Tôi muốn tạo một trang với một biểu mẫu và mỗi khi tôi gửi biểu mẫu, nó sẽ thêm một mục vào danh sách bên dưới biểu mẫu.Django - Trộn ListView và CreateView

tôi có thể làm cho nó hoạt động sử dụng 2 trang:

  • một trang bằng cách sử dụng mixin CreateView để thêm các mục
  • một trang ListView để có danh sách.

Nhưng tôi đang cố gắng có biểu mẫu và danh sách trên cùng một trang. Vì vậy, tôi đã cố gắng để tạo ra một lớp với cả mixin:

class FormAndListView(ListView, CreateView): 
    pass 

Sau đó, tôi đã sử dụng lớp này:

FormAndListView.as_view(
    queryset=PdfFile.objects.order_by('id'), 
    context_object_name='all_PDF', 
    success_url = 'listview', 
    form_class = UploadFileForm, 
    template_name='textfrompdf/index.html',)), 

Nhưng khi tôi cố gắng để tải trang, tôi nhận được lỗi: Exception Value: 'FormAndListView' object has no attribute 'object'

Traceback: 
File "C:\Program Files\Python_2.7\lib\site-packages\django\core\handlers\base.py" in get_response 
    111.       response = callback(request, *callback_args, **callback_kwargs) 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\base.py" in view 
    47.    return self.dispatch(request, *args, **kwargs) 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\base.py" in dispatch 
    68.   return handler(request, *args, **kwargs) 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\list.py" in get 
    122.   return self.render_to_response(context) 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\base.py" in render_to_response 
    94.    template = self.get_template_names(), 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\list.py" in get_template_names 
    134.    names = super(MultipleObjectTemplateResponseMixin, self).get_template_names() 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\detail.py" in get_template_names 
    122.   if self.object and self.template_name_field: 

Exception Type: AttributeError at /PDF/ 
Exception Value: 'FormAndListView' object has no attribute 'object' 

Tôi không biết cách gỡ lỗi đó. Bắt đầu từ đâu?

Trả lời

8

Tôi tìm thấy câu trả lời, có 2 vấn đề:

  • ListView và createView là "trình độ cao" mixin mà tổng hợp "thấp mức" mixins. Nhưng những mixin cấp thấp hơn này không tương thích với nhau.
  • Lớp Chế độ xem gọi trực tiếp hàm render_to_response(), nhưng trong trường hợp của tôi, có 2 lớp chế độ xem và render_to_response() chỉ nên được gọi một lần ở cuối.

tôi đã có thể "giải quyết" vấn đề này bằng cách sử dụng các bước sau:

Thay vì gọi ListView và createView, tôi sử dụng mixins cấp dưới.Hơn nữa tôi gọi rõ ràng là BaseCreateView và BaseListView mà từ đó tôi "trích xuất" biểu mẫu và object_list

class FormAndListView(BaseCreateView, BaseListView, TemplateResponseMixin): 
    def get(self, request, *args, **kwargs): 
     formView = BaseCreateView.get(self, request, *args, **kwargs) 
     listView = BaseListView.get(self, request, *args, **kwargs) 
     formData = formView.context_data['form'] 
     listData = listView.context_data['object_list'] 
     return render_to_response('textfrompdf/index.html', {'form' : formData, 'all_PDF' : listData}, 
          context_instance=RequestContext(request)) 

Nó không sạch sẽ nhưng nó hoạt động!

+6

Có quá nhiều điều xảy ra với quan điểm này và sẽ rất khó khăn để duy trì. Người dùng 'jondykeman' có giải pháp an toàn hơn và thanh lịch hơn cho vấn đề này. – zedr

8

Không trộn danh sách và cập nhật chế độ xem.
Thay vào đó, tạo ra hai quan điểm riêng biệt cho những công việc này:

Danh sách

xem hiển thị danh sách và một mẫu web với action URL trỏ đến các tạo view.
Tạo view chấp nhận dữ liệu POST và

  • màn hình với thông báo lỗi trong trường hợp thất bại;
  • chuyển hướng đến chế độ xem danh sách trong trường hợp thành công.

Ngoài ra tôi đã cố gắng sử dụng chế độ xem dựa trên lớp và nhận thấy rằng chúng quá phức tạp.
Tôi nghĩ rằng việc sử dụng chế độ xem kiểu cũ hơn sẽ dễ dàng hơn nhiều.

+1

Có, ý tưởng hay! Tôi sẽ làm điều đó, nhưng vì tôi mới bắt đầu với python và Django, tôi muốn hiểu tại sao nó không hoạt động hay cách khác để tìm ra nguồn gốc của sai lầm của tôi. Cảm ơn! – Nico

4

Tôi đã tạo lớp học của riêng mình để giải quyết vấn đề này. Tôi không biết nếu nó tốt hơn hay tệ hơn, nhưng nó cũng hoạt động. Tôi đã cố gắng sử dụng mixin chung và đã thử nghiệm việc xác nhận và phân trang.

The code in GitHub

class ListAppendView(MultipleObjectMixin, 
    MultipleObjectTemplateResponseMixin, 
    ModelFormMixin, 
    ProcessFormView): 
    """ A View that displays a list of objects and a form to create a new object. 
    The View processes this form. """ 
    template_name_suffix = '_append' 
    allow_empty = True 

    def get(self, request, *args, **kwargs): 
     self.object_list = self.get_queryset() 
     allow_empty = self.get_allow_empty() 
     if not allow_empty and len(self.object_list) == 0: 
      raise Http404(_(u"Empty list and '%(class_name)s.allow_empty' is False.") 
          % {'class_name': self.__class__.__name__}) 
     self.object = None 
     form_class = self.get_form_class() 
     form = self.get_form(form_class) 
     context = self.get_context_data(object_list=self.object_list, form=form) 
     return self.render_to_response(context) 

    def post(self, request, *args, **kwargs): 
     self.object = None 
     return super(ListAppendView, self).post(request, *args, **kwargs) 

    def form_invalid(self, form): 
     self.object_list = self.get_queryset() 
     return self.render_to_response(self.get_context_data(object_list=self.object_list, form=form)) 

Nếu bạn thử nó và tìm thấy bất kỳ lỗi, xin vui lòng cho tôi biết đây hoặc ở GitHub.

27

Tôi sử dụng nhiều lượt xem liên quan đến biểu mẫu và danh sách đối tượng. Thay vì cố gắng trộn lẫn mọi thứ, tôi chỉ thêm queryset vào dữ liệu ngữ cảnh như dưới đây.

class UploadFileView(CreateView): 
    form_class = UploadFileForm 
    success_url = 'listview' 
    template_name = 'textfrompdf/index.html' 

    def get_context_data(self, **kwargs): 
     kwargs['object_list'] = PdfFile.objects.order_by('id') 
     return super(UploadFileView, self).get_context_data(**kwargs) 
+5

Điều này có lẽ rất thanh lịch, nhưng nó sẽ giúp giải thích thêm. – highpost

+0

Có bất kỳ vấn đề nào với việc khởi động phân trang danh sách với cách sử dụng này không? – AlanSE

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