2013-04-02 24 views
55

Không rõ với tôi nó như thế nào là tốt nhất để truy cập vào URL thông số trong lớp học dựa trên quan điểm-trong Django 1.5.URL thông số và logic trong quan điểm dựa trên lớp Django (TemplateView)

xem xét như sau:

Xem:

from django.views.generic.base import TemplateView 


class Yearly(TemplateView): 
    template_name = "calendars/yearly.html" 

    current_year = datetime.datetime.now().year 
    current_month = datetime.datetime.now().month 

    def get_context_data(self, **kwargs): 
     context = super(Yearly, self).get_context_data(**kwargs) 
     context['current_year'] = self.current_year 
     context['current_month'] = self.current_month 
     return context 

URLconf:

from .views import Yearly 


urlpatterns = patterns('', 
    url(
     regex=r'^(?P<year>\d+)/$', 
     view=Yearly.as_view(), 
     name='yearly-view' 
    ), 
) 

tôi muốn truy cập các thông số year trong quan điểm của tôi, vì vậy tôi có thể làm luận như:

month_names = ["January", "February", "March", "April", "May", "June", "July", 
       "August", "September", "October", "November", "December"] 

    for month, month_name in enumerate(month_names, start=1): 
     is_current = False 
     if year == current_year and month == current_month: 
      is_current = True 
     months.append({ 
      'month': month, 
      'name': month_name, 
      'is_current': is_current}) 

Cách tốt nhất nên truy cập thông số url trong CBV như ở trên được phân loại là TemplateView và vị trí lý tưởng nên đặt logic như thế này, ví dụ: trong một phương pháp?

Trả lời

71

Để truy cập vào các thông số url trong quan điểm dựa trên lớp, sử dụng self.args hoặc self.kwargs do đó bạn sẽ truy cập nó bằng cách làm self.kwargs['year']

+1

Có hiểu một cách chính xác rằng tôi không được phép tạo ra các biến trực tiếp trong giao diện như tôi có ở trên? (một cái gì đó về họ được liên tục).Ngoài ra tôi không hiểu nơi tôi phải đặt logic như trên, ví dụ như. trong đó phương pháp nào? Ngoài ra khi tôi làm 'year = self.kwargs ['year']' trong khung nhìn tôi nhận được 'NameError: self not defined'. –

+2

Về mặt kỹ thuật bạn không nên vì chúng ở cấp lớp và là các biến lớp. Đối với 'NameError', bạn đang cố gắng làm' year = self.kwargs ['year'] 'ở đâu? Bạn nên làm điều đó trong một phương pháp, bạn không thể làm điều đó ở cấp lớp. Vì vậy, ví dụ, bạn đang sử dụng một 'TemplateView' có nghĩa là bạn sẽ làm logic trong ghi đè' get_context_data' của bạn. – Ngenator

+2

Chỉ để tham khảo: Bạn có thể tìm thấy tài liệu về self.request, self.args vv trong https://docs.djangoproject.com/en/1.10/topics/class-based-views/generic-display/ – LShi

7

Cho đến nay tôi đã chỉ có thể truy cập vào các thông số url từ bên trong phương pháp get_queryset, mặc dù Tôi đã chỉ thử nó với một ListView không phải là một TemplateView. Tôi sẽ sử dụng param url để tạo ra một thuộc tính trên trường hợp đối tượng, sau đó sử dụng thuộc tính rằng trong get_context_data để cư trú trong bối cảnh:

class Yearly(TemplateView): 
    template_name = "calendars/yearly.html" 

    current_year = datetime.datetime.now().year 
    current_month = datetime.datetime.now().month 

    def get_queryset(self): 
     self.year = self.kwargs['year'] 
     queryset = super(Yearly, self).get_queryset() 
     return queryset 

    def get_context_data(self, **kwargs): 
     context = super(Yearly, self).get_context_data(**kwargs) 
     context['current_year'] = self.current_year 
     context['current_month'] = self.current_month 
     context['year'] = self.year 
     return context 
+0

Tôi thấy rằng lẻ, là có một lỗi hoặc một cái gì đó khi bạn cố gắng làm 'bối cảnh ['năm'] = self.kwargs ['năm']'? Nó có thể truy cập được ở bất cứ đâu trong lớp. – Ngenator

+0

@Ngenator: Tôi vừa thiết lập một dự án django sạch để kiểm tra lại và hóa ra bạn chính xác. Tôi không chắc chắn những gì đã ngăn chặn điều này trong mã ban đầu của tôi nhưng tôi sẽ tìm hiểu :). Cảm ơn người đứng đầu – hellsgate

37

Trong trường hợp bạn vượt qua tham số URL như sau:

http://<my_url>/?order_by=created 

bạn có thể truy cập nó theo quan điểm dựa trên lớp bằng cách sử dụng self.request.GET (nó không được trình bày trong self.args cũng không phải trong self.kwargs):

class MyClassBasedView(ObjectList): 
    ... 
    def get_queryset(self): 
     order_by = self.request.GET.get('order_by') or '-created' 
     qs = super(MyClassBasedView, self).get_queryset() 
     return qs.order_by(order_by) 
+2

Cảm ơn! Điều này đã gây nhầm lẫn cho tôi ... Tôi tiếp tục đọc những thứ hàm ý các tham số HTTP sẽ nằm trong các kwargs. – foobarbecue

+0

Bạn có thể hiển thị get_queryset() của lớp cha của MyClassBasedView không? Tôi sẽ chỉ làm 'qs = .objects. ' – Timo

15

tôi thấy điều này giải pháp tao nhã, và cho django 1.5 hoặc cao hơn, như chỉ ra here:

Django’s generic class based views now automatically include a view variable in the context. This variable points at your view object.

Trong views.py của bạn:

from django.views.generic.base import TemplateView  

class Yearly(TemplateView): 
    template_name = "calendars/yearly.html" 
    # No here 
    current_year = datetime.datetime.now().year 
    current_month = datetime.datetime.now().month 

    # dispatch is called when the class instance loads 
    def dispatch(self, request, *args, **kwargs): 
     self.year = kwargs.get('year', "any_default") 

    # other code 

Các giải pháp công văn được tìm thấy trong question này.
Như view đã được thông qua trong bối cảnh Template, bạn không thực sự cần phải quan tâm đến nó. Trong file template yearly.html của bạn, nó có thể truy cập vào những điểm thuộc tính đơn giản bằng cách:

{{ view.year }} 
{{ view.current_year }} 
{{ view.current_month }} 

Bạn có thể giữ URLconf bạn như nó được.

Điều đáng nói là việc đưa thông tin vào bối cảnh mẫu của bạn sẽ ghi đè get_context_data(), do đó bằng cách nào đó, vi phạm luồng hành động của django là.

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