Sınıfa dayalı görünümlerin avantajı nedir?


82

Bugün Django 1.3 alpha'nın gönderildiğini ve en çok lanse edilen yeni özelliğin sınıf tabanlı görünümlerin tanıtılması olduğunu okudum . İlgili belgeleri
okudum , ancak onları kullanarak elde edebileceğim büyük avantajı ™ görmekte zorlanıyorum , bu yüzden burada onları anlamak için biraz yardım istiyorum. Dokümantasyondan gelişmiş bir örnek alalım .

urls.py

from books.views import PublisherBookListView

urlpatterns = patterns('',
    (r'^books/(\w+)/$', PublisherBookListView.as_view()),
)

views.py

from django.shortcuts import get_object_or_404
from django.views.generic import ListView
from books.models import Book, Publisher

class PublisherBookListView(ListView):

    context_object_name = "book_list"
    template_name = "books/books_by_publisher.html",

    def get_queryset(self):
        self.publisher = get_object_or_404(Publisher, name__iexact=self.args[0])
        return Book.objects.filter(publisher=self.publisher)

    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super(PublisherBookListView, self).get_context_data(**kwargs)
        # Add in the publisher
        context['publisher'] = self.publisher
        return context

Şimdi de bunu, bu soru için 5 dakika içinde kendi başıma yaptığım bir "sade eski görünüm" çözümüyle karşılaştıralım (içinde bulabileceğiniz herhangi bir hata için özür dilerim).

urls.py

urlpatterns = patterns('books.views',
    url(r'^books/(\w+)/$', 'publisher_books_list', name="publisher_books_list"),
)

views.py

from django.shortcuts import get_object_or_404
from books.models import Book, Publisher

def publisher_books_list(request, publisher_name):
    publisher = get_object_or_404(Publisher, name__iexact=publisher_name)
    book_list = Book.objects.filter(publisher=publisher)

    return render_to_response('books/books_by_publisher.html', {
        "book_list": book_list,
        "publisher": publisher,
    }, context_instance=RequestContext(request))

Bana göre ikinci versiyon:

  • İşlevsellik açısından eşdeğer
  • Çok daha okunaklı ( self.args[0]? Korkunç!)
  • Daha kısa
  • Daha az KURU uyumlu değil

Kaçırdığım büyük bir şey mi var? Neden kullanmalıyım? Belgelerdekiler mi? Öyleyse ideal kullanım durumu ne olurdu? Are Katmalar yararlı mı?

Katkıda bulunan herkese şimdiden teşekkürler!

PS merak edebilirsiniz olanlar için, ben de jenerik görünümleri tarafından büyülenmiş asla: en kısa zamanda bazı gelişmiş işlevsellik gerektiği gibi, düzenli görünümleri daha kısa hale geldi.


4
Evet ben de büyük bir avantajı görmüyorum. Bu konuda büyük bir cevap görmek isterim.
M. Ryan

1
Kesinlikle katılmak. Özellikle self.args [0] veya self.kwargs ['slug'] beni tiksindiriyor. Şu anda url parametreleri için varsayılan değerler sağlamak da çok daha zordur, örneğin: def publisher_books_list (istek,
yayıncı_adı

Yanıtlar:


48

Bir sınıfı alt sınıflandırabilir ve get_context_data gibi yöntemleri belirli durumlar için iyileştirebilir ve geri kalanını olduğu gibi bırakabilirsiniz. Bunu işlevlerle yapamazsınız.

Örneğin, bir öncekinin yaptığı her şeyi yapan yeni bir görünüm oluşturmanız gerekebilir, ancak bağlama fazladan değişken eklemeniz gerekir. Orijinal görünümü alt sınıfa ayırın ve get_context_data yöntemini geçersiz kılın.

Ayrıca, şablonu ayrı yöntemlere dönüştürmek için gereken adımların ayrılması, daha net kod sağlar - bir yöntemde ne kadar az yapılırsa, anlaşılması o kadar kolay olur. Normal görüntüleme işlevleriyle, hepsi tek bir işlem birimine aktarılır.


2
Evet, bunu görebiliyorum. RESTful'a, tam bir siteye veya bir mobil siteye sahip olmanız gerekip gerekmediğine karar vermeye çalışırken, geçersiz kılma kolaylığı ve sık karıştırma sağlar. Bununla, işlevsellik türetilirken bu karar mümkün olduğu kadar ertelenebilir. Pylons'daki Webware modülü buna sahipti ve çok faydalı oldu. Bununla birlikte, __call __ () yöntemini geçersiz kılarak, Django ile sınıf tabanlı görünümler uzun zamandır mümkün olmuştur.
Elf Sternberg

9
Cevabı çok iyi bir nokta sağladığı için kabul ediyorum ... ama çözmem gereken bu tür problemler nadiren yaşadığım için onları kullanma ihtiyacı hissetmiyorum. Teşekkürler!
Agos

18

Eğer self.args[0]sizi rahatsız, alternatif:

urlpatterns = patterns('books.views',
    url(r'^books/(?P<slug>\w+)/$', 'publisher_books_list', name="publisher_books_list"),
)

Daha sonra self.kwargs['slug']onu biraz daha okunaklı hale getirerek kullanabilirsiniz .


10

Örnek fonksiyonunuz ve sınıfınız özelliklerde eşit değildir.

Sınıf tabanlı sürüm ücretsiz olarak sayfalandırma sağlar ve GET dışındaki diğer HTTP fiillerinin kullanımını yasaklar.

Bunu işlevinize eklemek istiyorsanız, çok daha uzun sürecek.

Ama aslında daha karmaşık.


2
Farkı göstermek için +1, ama kişisel olarak, require_GET ve django-sayfalandırmanın kullanımı önemsiz, özlü, açık vb. Olduğunu düşünüyorum ve her zaman (neredeyse :)) cbv'lere tercih ediyorum.
Tomasz Zieliński

4

Bunu ilk duyuyorum - ve hoşuma gidiyor.

Dürüst olmak gerekirse, burada gördüğüm avantaj, görüşleri genel olarak Django ile daha tutarlı hale getirmesidir. Modeller sınıftır ve her zaman görüşlerin de olması gerektiğini düşündüm. Her şeyin olduğunu bilmiyorum ama görünümler ve modeller en çok kullanılan iki tür .

Teknik avantaja gelince? Python'da her şey bir sınıftır ( veya nesnedir ?) - yani gerçekten bir fark var mı? İlk etapta% 99 sözdizimsel şeker değil mi?


Tutarlılığın daha fazla kod yeniden kullanımına izin verdiğini söyleyebilirim. Görüşleriniz belirli modellere uyuyorsa, temelde çok sayıda standart metni azaltıyorlar. örneğin, aa modeline dayalı bir form, sınıf tabanlı görünümlerle oluşturulması son derece hızlıdır. Birkaç ekstra alana ihtiyaç duyarsa, biraz daha zorlaşmaya başlar. Üç model artı iki ekstra alana dayalı bir forma ihtiyacınız varsa, bunlar muhtemelen size hiç çaba harcamayacaklardır.
wobbily_col

1

Sınıf temelli görünümler hakkında düşünmenin bir yolu, eğitim tekerlekleri kapalı bir Django yöneticisi gibi olmaları ve bu nedenle çok daha esnek (ancak anlaşılması daha zor) olmalarıdır.

Örneğin, yöneticideki liste görüntüsü açıkça genel ListView'e dayanmaktadır. En basit liste görünümü, yalnızca bir model veya sorgu kümesi tanımlar.

class MyExampleView(ListView);
    model = ExampleModel 

Kendi şablonunuzu sağlamanız gerekecek, ancak temelde en temel ModelAdmin ile aynı olacaktır. Model yöneticisindeki list_display özniteliği, ona hangi alanların görüntüleneceğini söyleyecektir, oysa ListView'de bunu şablonda yaparsınız.

class SpeciesAdmin(admin.ModelAdmin):
    list_display = ['name']
admin.site.register(ExampleModel , ExampleModelAdmin)

Yönetici ile bir parametreniz var

list_per_page = 100

bu, sayfa başına kaç tane nesneyi tanımlar. Liste görünümünde

paginate_by = 100

aynı şeyi başarır. Aynı şekilde, yöneticiyi büyük ölçüde özelleştirmeye bakarsanız, çok fazla örtüşme göreceksiniz.

Buradaki bu site size ne yaptıkları hakkında daha iyi bir fikir vermelidir.

http://ccbv.co.uk/

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.