Klasse utsikt i Django

stemmer
50

Django utsiktspunkter til en funksjon, som kan være et problem hvis du ønsker å endre bare en bit av funksjonalitet. Ja, jeg kunne ha million søkeord argumenter og enda mer hvis uttalelser i funksjon, men jeg tenkte mer på et objektorientert tilnærming.

For eksempel har jeg en side som viser en bruker. Denne siden er veldig lik side som viser en gruppe, men det er fortsatt ikke så lik bare bruke en annen datamodell. Konsernet har også medlemmer osv ...

En måte ville være å peke utsikt til klassemetoder og deretter utvide den klassen. Har noen prøvd denne tilnærmingen, eller har noen annen ide?

Publisert på 03/08/2008 klokken 15:55
kilden bruker
På andre språk...                            


9 svar

stemmer
42

Jeg har opprettet og brukt mine egne generiske vise klasser, definerer __call__så en forekomst av klassen er callable. Jeg liker det; mens Django sin generiske visninger lar noen tilpasning gjennom søkeord argumenter, kan OO generiske visninger (hvis deres atferd er delt inn i en rekke separate metoder) har mye mer finkornet tilpasning via subclassing, som lar meg gjenta meg selv mye mindre. (Jeg blir lei av å skrive om det samme opprette / oppdatere visningen logikk når jeg trenger å justere noe Django sin generiske synspunkter ikke helt tillate).

Jeg har lagt ut noen kode på djangosnippets.org .

Den eneste reelle ulemper jeg ser er spredning av interne metodekall, som kan påvirke ytelsen noe. Jeg tror ikke dette er mye av en bekymring; det er sjelden at Python kode ville være ytelsen flaskehals i en web-app.

OPPDATERING : Django egne generiske synspunkter er nå klassebasert.

OPPDATERING : FWIW, har jeg endret min mening på klassebaserte visninger siden dette svaret ble skrevet. Etter å ha brukt dem mye på et par prosjekter, føler jeg de har en tendens til å føre til kode som er satisfyingly TØRR å skrive, men veldig vanskelig å lese og vedlikeholde senere, fordi funksjonaliteten er spredt over så mange forskjellige steder, og underklasser er så avhengige på hver implementering detalj av super og mixins. Jeg føler nå at TemplateResponse og vise dekoratører er et bedre svar for rotne visning kode.

Svarte 29/08/2008 kl. 04:29
kilden bruker

stemmer
13

Jeg trengte å bruke klassebaserte visninger, men jeg ønsket å være i stand til å bruke fullt navn på klassen min URLconf uten alltid å på å bruke visningen klassen før du bruker den. Det som hjalp meg var en overraskende enkel metaclass:

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)

Jeg kan nå instantiate både utsikt klasser og bruke de tilfellene som visningsfunksjoner, eller jeg kan bare peke min URLconf til min klasse og har metaclass instantiate (og kaller) utsikten klasse for meg. Dette fungerer ved å sjekke det første argumentet til __call__- hvis det er en HttpRequest, det må være en faktisk HTTP-forespørsel fordi det ville være meningsløst å attept på å bruke en visning klasse med et HttpRequesteksempel.

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'),
)

(Jeg postet en tekstutdrag for dette på http://djangosnippets.org/snippets/2041/ )

Svarte 27/05/2010 kl. 13:02
kilden bruker

stemmer
10

Hvis du bare viser data fra modeller, hvorfor ikke bruke Django Generiske Views ? De er designet for å la deg enkle viser data fra en modell uten å måtte skrive ditt eget syn og ting om kartlegging URL paramaters til utsikt, henting av data, håndtering edge tilfeller, rendering utgang, etc.

Svarte 07/08/2008 kl. 10:44
kilden bruker

stemmer
3

Du kan alltid lage en klasse, overstyre __call__funksjonen og velg deretter URL-filen til en forekomst av klassen. Du kan ta en titt på FormWizard klasse for å se hvordan dette gjøres.

Svarte 26/08/2008 kl. 11:38
kilden bruker

stemmer
2

Med mindre du ønsker å gjøre noe litt komplisert, bruker de generelle utsikten er veien å gå. De er langt kraftigere enn navnet tilsier, og hvis du bare viser modellen data generiske synspunkter vil gjøre jobben.

Svarte 11/08/2008 kl. 22:59
kilden bruker

stemmer
2

Høres for meg ut som du prøver å kombinere ting som ikke bør kombineres. Hvis du trenger å gjøre annerledes behandling i ditt syn avhengig av om det er en bruker eller gruppe objektet du prøver å se på så bør du bruke to forskjellige visningsfunksjoner.

På den annen side kan det være felles idiomer du ønsker å trekke ut av object_detail synspunkter type ... kanskje du kunne bruke en dekoratør eller bare hjelpefunksjoner?

-Dan

Svarte 03/08/2008 kl. 17:40
kilden bruker

stemmer
1

Du kan bruke Django Generiske Views. Du kan enkelt oppnå ønsket funksjonalitet grundige Django generiske Visninger

Svarte 08/10/2014 kl. 05:53
kilden bruker

stemmer
1

Generiske visninger vil vanligvis være veien å gå, men til syvende og sist du er fri til å håndtere webadresser slik du vil. FormWizard gjør ting på en klassebasert måte, som gjør noen apps for RESTful APIer.

I utgangspunktet med en URL får du en haug med variabler og plass for å gi en callable, hva oppsigelige du gir er helt opp til deg - den vanlige måten er å gi en funksjon - men til slutt Django setter ingen begrensninger på hva du gjør.

Jeg er enig i at noen flere eksempler på hvordan du gjør dette ville være bra, er FormWizard trolig stedet å starte selv.

Svarte 23/09/2008 kl. 19:05
kilden bruker

stemmer
1

Hvis du ønsker å dele felles funksjonalitet mellom sidene foreslår jeg at du ser på egendefinerte koder. De er ganske enkle å lage , og er svært kraftig.

Dessuten kan maler strekke seg fra andre maler . Dette tillater deg å ha en base mal for å sette opp oppsettet av siden og for å dele denne mellom andre maler som fyller ut feltene. Du kan neste maler til enhver dybde; slik at du kan angi oppsettet på separate grupper av relaterte sider på ett sted.

Svarte 26/08/2008 kl. 11:30
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more