Skip to content

Latest commit

 

History

History
138 lines (103 loc) · 5.28 KB

9. CRUD on DBs.md

File metadata and controls

138 lines (103 loc) · 5.28 KB

In Django

Django mette a disposizione delle views per i metodi CRUD. Appartengono ai moduli django.views.generic.*.

È presente una classe View per ogni operazione CRUD:

  • CreateView
  • ListView: elenca le entry di una tabella, ritornandolo come QuerySet in automatico
  • UpdateView
  • DeleteView
  • DetailView

ListView

from django.views.generic import ListView

class ListStudentsView(ListView):
	model = Student
	template_name = 'iscrizioni/stud_list.html'

Come rendere raggiungibile questa classe tramite l'url routing? #Nota a differenza dei precedenti esempi è una class view, non una function view

In path inseriamo: path('studlist', views.ListStudentsView.as_view(), name='studlist')

Perché non specifichiamo il contesto? è ovvio dall'operazione che stiamo facendo. Il risultato è in object_list: una variabile di contesto che contiene il risultato (come QuerySet) della ListView.

Preprocessing con class views

Come con le function view, anche con le class view, posso fare preprocessing sul QuerySet passato alla vista.

DaView generiche sono ereditati i metodi:

  • get_queryset: per fare operazioni sul QuerySet ritornato dalla vista, dipendentemente dal modello selezionato
  • get_context_data: per aggiungere variabili di contesto

Posso fare override dei metodi:

class ListaInsegnamentiAttivi(ListView):
	model = Insegnamento
	template_name = 'iscrizioni/insegnamenti_attivi.html'

	def get_queryset(self):
		return self.model.objects.exclude(studenti__isnull = True)

	def get_context_data(self, *+kwargs):
		context = super().get_context_data(**kwargs)
		context['titolo'] = 'Insegnamenti Attivi'
		return context

Posso assicurarmi di star facendo override del metodo con la notazione @override offerta da Django.

Metodi di class views

Usando le view generiche di Django, otteniamo gratuitamente, all'interno del contesto, una variabile view. Ovvero un riferimento alla view class dalla quale stiamo rispondendo. Possiamo quindi chiamare dalla vista i metodi della classe.

Dal template non posso chiamare metodi con argomenti (escluso self), per mantenere il paradigma MTV ben delineato.

CreateView

È una view pre-confezionata che permette di creare entry per una tabella.

Come al solito, devo specificare model e template.

In più:

  • fields posto uguale ad una lista contenente i campi della relazione da compilare, oppure '__all__'
  • success_url = reverse_lazy('iscrizioni:listastudenti'. La funzione reverse_lazy inibisce la lazy evaluation dell'endpoint specificato

Esiste un'altra funzione simile: reverse Questa funzione ha la stessa firma di reverse_lazy, ma si usa come valore di ritorno dai metodi. La ragione per cui esistono queste funzioni risiede nella lazy evaluation delle classi in Python. Infatti, per valutare un attributo di istanza, è necessario eseguire il corpo della funzione; questo può avvenire in momenti diversi a seconda dell'implementazione.

Lato view, abbiamo delle utility già fatte:

<form method='post'> {% csrf_token %}
	{{ form.as_p }}
	<input type='sumbit' value'Save'>
</form>

Perché post? con GET alcuni tipi di dato non possono essere passati. Eg. files.

Il dizionario con cui ottenere parametri passati con metodo POST può essere acceduto con request.POST['name']

Cos'è csrf_token? È un meccanismo di sicurezza che siamo obbligati ad utilizzare nel DTL. Serve per evitare Cross Site Reference Forgery. Si tratta di un token associato al form, ottenuto in base all'utente che sta utilizzando il sito; l'identificazione può avvenire mediante sessione o autenticazione. È gestito dal Django middleware.

Il controllo sui vincoli dei campi è sia lato client che lato server.

#Vedi differenze tra GET e POST: bookmarking, caching, idempotenza

Detail View

Ha un comportamento simile alla ListView, ma ritorna un dettaglio, ovvero una sola entry della relazione. L'elemento è specificato tramite url path.

path('studente/<pk>', ...)

class InsegnamentoView(DetailView):
	model = Insegnamento
	template_name = 'iscrizioni/insegnamento.html'

Update View

Ritorna una vista che presenta un form precompilato, mediante il quale sono modificabili alcune celle della entry. L'elemento è specificato con url path.

class UpddateInsegnamentoView(UpdateView):
	model = Insegnamento
	template_name = 'iscrizioni/edit_insegnamento.html'
	fields = '__all__'
	
	def get_success_url(self):
		pk = self.get_context_data()['object'].pk
		return reverse('iscrizioni:insegnamento', kwargs={'pk'=pk})

DeleteView

Similmente a update a detail, l'elemento da eliminare è specificato mediante url path.

class DeleteEntitaView(DeleteView):
	template_name = 'iscrizioni/cancella_studente.html'

	def get_context_data(self, **kwargs):
		ctx = super().get_context_data()
		entita = 'Studente' if self.model == Studenti else 'Insegnante'
		ctx['entita'] = entita
		return ctx

	def get_success_url(self):
		url = 'iscrizioni:lista_insegnamenti'if self.model == Insegnamento else 'iscrizioni:lista_studenti'
		return reverse(url)

CBV

Ad esempio, ritornare elementi filtrati secondo un criterio passato nell'url path, può essere fatto definendo un metodo annidato nella class view.

def get_queryset(self):
	surname = self.kwargs['cognome']
	# filter
	# and then return