2008-08-03 48 views
45

Django xem điểm đến một hàm, có thể là vấn đề nếu bạn chỉ muốn thay đổi một chút chức năng. Có, tôi có thể có hàng triệu đối số từ khóa và thậm chí nhiều hơn nếu các câu lệnh trong hàm, nhưng tôi đã suy nghĩ nhiều hơn về cách tiếp cận hướng đối tượng.Chế độ xem lớp ở Django

Ví dụ: tôi có trang hiển thị người dùng. Trang này rất giống với trang hiển thị một nhóm, nhưng nó vẫn không tương tự như chỉ sử dụng một mô hình dữ liệu khác. Nhóm cũng có các thành viên, v.v ...

Một cách sẽ là quan điểm điểm đến các phương thức lớp và sau đó mở rộng lớp đó. Có ai đã thử phương pháp này hay có ý tưởng nào khác không?

Trả lời

41

Tôi đã tạo và sử dụng các lớp chế độ xem chung của riêng mình, xác định __call__ để phiên bản của lớp có thể gọi được. Tôi thực sự thích nó; trong khi các chế độ xem chung của Django cho phép một số tùy chỉnh thông qua các đối số từ khóa, các khung nhìn chung của OO (nếu hành vi của chúng được chia thành một số phương thức riêng biệt) có thể có nhiều tùy chỉnh chi tiết hơn thông qua phân lớp, cho phép tôi lặp lại bản thân ít hơn nhiều. (Tôi cảm thấy mệt mỏi khi viết lại cùng một logic tạo/cập nhật xem bất cứ lúc nào tôi cần phải chỉnh sửa một cái gì đó của Django nhìn chung chung không hoàn toàn cho phép).

Tôi đã đăng một số mã tại djangosnippets.org.

Nhược điểm thực sự duy nhất tôi thấy là sự gia tăng của các cuộc gọi phương thức nội bộ, điều này có thể ảnh hưởng đến hiệu năng. Tôi không nghĩ rằng đây là một mối quan tâm lớn; hiếm khi thực thi mã Python sẽ là nút cổ chai hiệu suất của bạn trong ứng dụng web.

CẬP NHẬT: Riêng của Django generic views hiện là dựa trên lớp học.

CẬP NHẬT: FWIW, tôi đã thay đổi ý kiến ​​của mình về lượt xem dựa trên lớp học kể từ khi câu trả lời này được viết. Sau khi đã sử dụng chúng rộng rãi trên một vài dự án, tôi cảm thấy chúng có xu hướng dẫn đến mã đáp ứng DRY để viết, nhưng rất khó đọc và duy trì sau, bởi vì chức năng được lan truyền trên nhiều nơi khác nhau, và các lớp con phụ thuộc quá nhiều trên mọi chi tiết triển khai của các siêu lớp và mixin. Bây giờ tôi cảm thấy rằng TemplateResponse và xem trang trí là một câu trả lời tốt hơn cho việc phân tích mã xem.

+0

Thực thi Python không phải là nút cổ chai, nhưng có thể ảnh hưởng đến khả năng mở rộng trang web và hiệu suất tổng thể. Tôi rất vui vì memcache tồn tại! – StefanNch

2

Nghe có vẻ như bạn đang cố kết hợp những thứ không nên kết hợp. Nếu bạn cần thực hiện xử lý khác trong chế độ xem của mình, tùy thuộc vào đó là đối tượng Người dùng hoặc Nhóm bạn đang cố xem xét thì bạn nên sử dụng hai chức năng chế độ xem khác nhau.

Mặt khác, có thể có các thành ngữ phổ biến bạn muốn tách ra khỏi đối tượng của mình _ kiểu xem chi tiết ... có lẽ bạn có thể sử dụng một công cụ trang trí hoặc chỉ các hàm trợ giúp?

-Dan

9

Nếu bạn chỉ đơn giản là hiển thị dữ liệu từ các mô hình, tại sao không sử dụng Django Generic Views? Chúng được thiết kế để cho phép bạn dễ dàng hiển thị dữ liệu từ mô hình mà không phải viết chế độ xem của riêng bạn và các công cụ về ánh xạ các tham số URL cho các chế độ xem, tìm nạp dữ liệu, xử lý các trường hợp cạnh, kết xuất hiển thị, v.v.

2

Trừ khi bạn muốn thực hiện một cái gì đó phức tạp một chút, bằng cách sử dụng các quan điểm chung là con đường để đi. Chúng mạnh hơn nhiều so với tên của chúng, và nếu bạn chỉ hiển thị các khung nhìn chung của dữ liệu mô hình sẽ thực hiện công việc.

1

Nếu bạn muốn chia sẻ chức năng chung giữa các trang, tôi khuyên bạn nên xem các thẻ tùy chỉnh. Chúng khá là easy to create và rất mạnh mẽ.

Ngoài ra, templates can extend from other templates. Điều này cho phép bạn có một mẫu cơ sở để thiết lập bố cục của trang và chia sẻ nó giữa các mẫu khác điền vào các khoảng trắng. Bạn có thể lồng mẫu đến bất kỳ độ sâu nào; cho phép bạn chỉ định bố cục trên các nhóm trang liên quan riêng biệt ở một nơi.

+0

Tôi không nghĩ đặt quá nhiều logic vào mẫu là một ý tưởng hay. –

3

Bạn luôn có thể tạo lớp, ghi đè hàm __call__ và sau đó trỏ tệp URL vào một phiên bản của lớp. Bạn có thể xem lớp học FormWizard để biết cách thực hiện điều này.

+0

Bộ xử lý đánh dấu đã ăn \ _ \ _ của bạn. Sử dụng \\ _ để ẩn đánh dấu. Phương thức \ _ \ _ gọi \ _ \ _ của lớp là những gì được gọi. Vấn đề là để đảm bảo rằng urls.py có một thể hiện của lớp có sẵn cho nó. Điều này khiến cho url của bạn trở nên phức tạp hơn. –

1

Chế độ xem chung thường sẽ là cách để đi, nhưng cuối cùng bạn được tự do xử lý các URL theo ý bạn muốn. FormWizard thực hiện mọi thứ theo cách dựa trên lớp, cũng như một số ứng dụng cho RESTful APIs. Về cơ bản với một URL bạn được cung cấp một loạt các biến và đặt để cung cấp một cuộc gọi, những gì bạn gọi là cung cấp hoàn toàn tùy thuộc vào bạn - cách tiêu chuẩn là cung cấp một chức năng - nhưng cuối cùng Django không hạn chế về những gì bạn làm.

Tôi đồng ý rằng một vài ví dụ khác về cách thực hiện điều này sẽ tốt, FormWizard có lẽ là nơi bắt đầu.

13

Tôi cần sử dụng chế độ xem dựa trên lớp học, nhưng tôi muốn có thể sử dụng tên đầy đủ của lớp trong URLconf mà không phải khởi tạo lớp xem trước khi sử dụng. Có gì giúp tôi là một metaclass đáng ngạc nhiên đơn giản:

class CallableViewClass(type): 
    def __call__(cls, *args, **kwargs): 
     if args and isinstance(args[0], HttpRequest): 
      instance = super(CallableViewClass, cls).__call__() 
      return instance.__call__(*args, **kwargs) 
     else: 
      instance = super(CallableViewClass, cls).__call__(*args, **kwargs) 
      return instance 


class View(object): 
    __metaclass__ = CallableViewClass 

    def __call__(self, request, *args, **kwargs): 
     if hasattr(self, request.method): 
      handler = getattr(self, request.method) 
      if hasattr(handler, '__call__'): 
       return handler(request, *args, **kwargs) 
     return HttpResponseBadRequest('Method Not Allowed', status=405) 

tôi bây giờ có thể cả hai nhanh chóng lớp xem và sử dụng các trường hợp như xem chức năng, HOẶC tôi chỉ đơn giản có thể chỉ URLconf tôi đến lớp của tôi và có thuyết minh metaclass (và cuộc gọi) lớp xem cho tôi. Điều này hoạt động bằng cách kiểm tra đối số đầu tiên là __call__ - nếu đó là một HttpRequest, nó phải là một yêu cầu HTTP thực tế bởi vì sẽ vô nghĩa khi thực hiện khởi tạo lớp xem với một phiên bản HttpRequest.

class MyView(View): 
    def __init__(self, arg=None): 
     self.arg = arg 
    def GET(request): 
     return HttpResponse(self.arg or 'no args provided') 

@login_required 
class MyOtherView(View): 
    def POST(request): 
     pass 

# And all the following work as expected. 
urlpatterns = patterns('' 
    url(r'^myview1$', 'myapp.views.MyView', name='myview1'), 
    url(r'^myview2$', myapp.views.MyView, name='myview2'), 
    url(r'^myview3$', myapp.views.MyView('foobar'), name='myview3'), 
    url(r'^myotherview$', 'myapp.views.MyOtherView', name='otherview'), 
) 

(tôi đã đăng một đoạn mã cho điều này tại http://djangosnippets.org/snippets/2041/)

+1

hoàn toàn tuyệt vời – Anentropic

1

Bạn có thể sử dụng Views Django Chung. Bạn có thể dễ dàng đạt được chức năng mong muốn triệt để Django generic Views

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