Come posso inviare un modulo dato solo l'origine HTML?
-
19-08-2019 - |
Domanda
Vorrei poter inviare un modulo in un sorgente HTML (stringa) . In altre parole, ho bisogno almeno della capacità di generare i parametri POST da una stringa contenente l'origine HTML del modulo . Ciò è necessario nei test unitari per un progetto Django. Vorrei una soluzione che possibilmente;
- Utilizza solo la libreria Python standard e Django.
- Consente la generazione di parametri da un modulo specifico se è presente più di un modulo.
- Mi consente di modificare i valori prima dell'invio.
Una soluzione che restituisce un'istanza di modulo (Django) da una data classe di form è la migliore. Perché mi permetterebbe di usare la validazione. Idealmente, consumerebbe l'origine (che è una stringa), una classe di modulo e facoltativamente un nome di modulo e restituire l'istanza com'era prima del rendering.
NOTA: sono consapevole che questo non è un compito facile e probabilmente i guadagni difficilmente giustificheranno lo sforzo necessario. Ma sono solo curioso di sapere come farlo, in modo pratico e affidabile. Se possibile.
Soluzione
Dovresti rileggere la relativa al framework di test di Django , in particolare la parte relativa al test di viste (e moduli) con il client di test .
Il client di test funge da semplice browser Web e consente di inviare richieste GET
e POST
alle visualizzazioni Django. Puoi leggere l'HTML di risposta o ottenere lo stesso oggetto Context
ricevuto dal modello. Il tuo oggetto Context
dovrebbe contenere gli attuali form.Form
che stai cercando.
Ad esempio, se la tua vista nell'URL / form /
passa il contesto {'myform': forms.Form ()}
al modello, potresti arrivare in questo modo:
from django.test.client import Client
c = Client()
# request the web page:
response = c.get('/form/')
# get the Form object:
form = response.context['myform']
form_data = form.cleaned_data
my_form_data = {} # put your filled-out data in here...
form_data.update(my_form_data)
# submit the form back to the web page:
new_form = forms.Form(form_data)
if new_form.is_valid():
c.post('/form/', new_form.cleaned_data)
Speriamo che realizzi quello che vuoi, senza dover fare confusione con l'analisi dell'HTML.
Modifica : dopo aver riletto i documenti Django sui moduli, si scopre che i moduli sono immutabili. Va bene, però, basta creare una nuova istanza Form
e inviarla; Ho modificato il mio esempio di codice in modo che corrisponda a questo.
Altri suggerimenti
Dato che il framework di test di Django fa questo, non sono sicuro di cosa tu stia chiedendo.
Vuoi testare un'app Django che ha un modulo?
- In tal caso, devi fare un GET iniziale
- seguito dal POST risultante
Vuoi scrivere (e testare) un'app Django che invia un modulo a un altro sito?
Ecco come testiamo le app di Django con i moduli.
class Test_HTML_Change_User( django.test.TestCase ):
fixtures = [ 'auth.json', 'someApp.json' ]
def test_chg_user_1( self ):
self.client.login( username='this', password='this' )
response= self.client.get( "/support/html/user/2/change/" )
self.assertEquals( 200, response.status_code )
self.assertTemplateUsed( response, "someApp/user.html")
def test_chg_user( self ):
self.client.login( username='this', password='this' )
# The truly fussy would redo the test_chg_user_1 test here
response= self.client.post(
"/support/html/user/2/change/",
{'web_services': 'P',
'username':'olduser',
'first_name':'asdf',
'last_name':'asdf',
'email':'asdf@asdf.com',
'password1':'passw0rd',
'password2':'passw0rd',} )
self.assertRedirects(response, "/support/html/user/2/" )
response= self.client.get( "/support/html/user/2/" )
self.assertContains( response, "<h2>Users: Details for", status_code=200 )
self.assertContains( response, "olduser" )
self.assertTemplateUsed( response, "someApp/user_detail.html")
Nota: non analizziamo l'HTML in dettaglio. Se ha il modello giusto e ha la stringa di risposta giusta, deve essere giusto.
È semplice ... e difficile allo stesso tempo.
Disclaimer: non so molto di Python e niente di Django ... Quindi do consigli generali, non linguistici ...
Se uno dei suddetti consigli non funziona per te, ti consigliamo di farlo manualmente:
- Carica la pagina con un parser HTML, elenca i moduli.
- Se l'attributo
method
è POST (senza distinzione tra maiuscole e minuscole), ottenere l'attributoaction
per ottenere l'URL della richiesta (può essere relativo). - Nel modulo, ottieni tutti i tag
input
eselect
. Gli attributiname
(oid
se nessun nome) sono le chiavi dei parametri della richiesta. Gli attributivalue
(vuoto se assente) sono i valori corrispondenti. - Per
seleziona
, il valore è quello dell'opzioneselezionata
o il testo visualizzato non è un attributovalue
.
Questi nomi e valori devono essere codificati nell'URL nelle richieste GET, ma non in quelle POST.
HTH.
Scopri meccanizzare o è il wrapper twill . Penso che sia ClientForm funzionerà per te.