Saya baru saja mulai bekerja dengan Django yang berasal dari Spring MVC selama bertahun-tahun dan implementasi formulir terasa sedikit gila. Jika Anda tidak terbiasa, formulir Django dimulai dengan kelas model formulir yang mendefinisikan bidang Anda. Musim semi juga dimulai dengan objek dukungan bentuk. Tetapi di mana Spring menyediakan taglib untuk mengikat elemen formulir ke objek dukungan dalam JSP Anda, Django memiliki widget formulir yang diikat langsung ke model. Ada widget default tempat Anda dapat menambahkan atribut style ke bidang Anda untuk menerapkan CSS atau mendefinisikan widget khusus sepenuhnya sebagai kelas baru. Semuanya ada dalam kode python Anda. Sepertinya itu gila bagi saya. Pertama, Anda menempatkan informasi tentang tampilan Anda langsung di model Anda dan kedua Anda mengikat model Anda ke tampilan tertentu. Apakah saya melewatkan sesuatu?
EDIT: Beberapa kode contoh seperti yang diminta.
Django:
# Class defines the data associated with this form
class CommentForm(forms.Form):
# name is CharField and the argument tells Django to use a <input type="text">
# and add the CSS class "special" as an attribute. The kind of thing that should
# go in a template
name = forms.CharField(
widget=forms.TextInput(attrs={'class':'special'}))
url = forms.URLField()
# Again, comment is <input type="text" size="40" /> even though input box size
# is a visual design constraint and not tied to the data model
comment = forms.CharField(
widget=forms.TextInput(attrs={'size':'40'}))
Spring MVC:
public class User {
// Form class in this case is a POJO, passed to the template in the controller
private String firstName;
private String lastName;
get/setWhatever() {}
}
<!-- JSP code references an instance of type User with custom tags -->
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!-- "user" is the name assigned to a User instance -->
<form:form commandName="user">
<table>
<tr>
<td>First Name:</td>
<!-- "path" attribute sets the name field and binds to object on backend -->
<td><form:input path="firstName" class="special" /></td>
</tr>
<tr>
<td>Last Name:</td>
<td><form:input path="lastName" size="40" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save Changes" />
</td>
</tr>
</table>
</form:form>
Jawaban:
Ya, bentuk Django berantakan dari perspektif MVC, misalkan Anda bekerja di game pahlawan super MMO besar dan Anda membuat model Pahlawan:
Sekarang Anda diminta untuk membuat formulir untuk itu, sehingga para pemain MMO dapat memasukkan kekuatan super pahlawan mereka:
Karena Penolak Hiu adalah senjata yang sangat kuat, bos Anda meminta Anda untuk membatasi itu. Jika seorang pahlawan memiliki Penolak Hiu maka dia tidak bisa terbang. Apa yang dilakukan kebanyakan orang hanyalah menambahkan aturan bisnis ini dalam formulir bersih dan menyebutnya sehari:
Pola ini terlihat keren dan mungkin bekerja pada proyek-proyek kecil, tetapi dalam pengalaman saya ini sangat sulit untuk dipertahankan dalam proyek-proyek besar dengan banyak pengembang. Masalahnya adalah bahwa formulir adalah bagian dari pandangan MVC. Jadi, Anda harus ingat aturan bisnis itu setiap kali Anda:
Maksud saya di sini adalah bahwa forms.py adalah semua tentang tata letak formulir dan presentasi, Anda tidak boleh menambahkan logika bisnis dalam file itu kecuali Anda menikmati bermain-main dengan kode spaghetti.
Cara terbaik untuk menangani masalah pahlawan adalah dengan menggunakan metode model clean plus sinyal khusus. Model clean berfungsi seperti form clean tetapi disimpan dalam model itu sendiri, setiap kali HeroForm dibersihkan secara otomatis memanggil metode Hero clean. Ini adalah praktik yang baik karena jika pengembang lain menulis formulir lain untuk Pahlawan, ia akan mendapatkan validasi penolak / lalat secara gratis.
Masalah dengan bersih adalah bahwa itu dipanggil hanya ketika Model dimodifikasi oleh formulir. Itu tidak dipanggil ketika Anda secara manual menyimpan () dan Anda dapat berakhir dengan pahlawan yang tidak valid di database Anda. Untuk mengatasi masalah ini, Anda dapat menambahkan pendengar ini ke proyek Anda:
Ini akan memanggil metode bersih pada setiap panggilan save () untuk semua model Anda.
sumber
Anda sedang mencampur seluruh tumpukan, ada beberapa lapisan yang terlibat:
Model Django mendefinisikan struktur data.
Formulir Django adalah jalan pintas untuk menentukan formulir HTML, validasi bidang, dan terjemahan nilai Python / HTML. Ini tidak sepenuhnya dibutuhkan, tetapi sering kali berguna.
Django ModelForm adalah jalan pintas lain, singkatnya subclass Formulir yang mendapatkan bidangnya dari definisi Model. Hanya cara praktis untuk kasus umum di mana formulir digunakan untuk memasukkan data ke dalam basis data.
dan akhirnya:
Beberapa orang melihatnya sebagai bid'ah; tetapi penting untuk diingat bahwa MVC pada awalnya ditentukan untuk aplikasi GUI, dan itu agak canggung untuk aplikasi web.
sumber
Saya menjawab pertanyaan lama ini karena jawaban lain tampaknya menghindari masalah spesifik yang disebutkan.
Formulir Django memungkinkan Anda untuk dengan mudah menulis kode kecil dan membuat formulir dengan standar waras. Setiap jumlah penyesuaian sangat cepat mengarah ke "lebih banyak kode" dan "lebih banyak pekerjaan" dan agak membatalkan manfaat utama dari sistem formulir
Perpustakaan templat seperti django-widget-tweaks membuat menyesuaikan formulir lebih mudah. Semoga kustomisasi bidang seperti ini pada akhirnya akan mudah dengan instalasi vanilla Django.
Contoh Anda dengan django-widget-tweaks:
sumber
(Saya telah menggunakan Miring untuk menandakan konsep MVC untuk membuat ini lebih mudah dibaca.)
Tidak, menurut saya, mereka tidak merusak MVC. Ketika bekerja dengan Model / Formulir Django, anggap itu menggunakan seluruh tumpukan MVC sebagai Model :
django.db.models.Model
adalah Model dasar (memegang data dan logika bisnis).django.forms.ModelForm
menyediakan Controller untuk berinteraksi dengandjango.db.models.Model
.django.forms.Form
(seperti yang disediakan melalui pewarisan olehdjango.forms.ModelForm
) adalah View yang berinteraksi dengan Anda.ModelForm
aForm
, sehingga dua lapisan yang erat. Menurut pendapat saya, ini dilakukan untuk singkatnya kode kami, dan untuk penggunaan kembali kode dalam kode pengembang Django.Dengan cara ini,
django.forms.ModelForm
(dengan data dan logika bisnisnya) menjadi Model itu sendiri. Anda bisa merujuknya sebagai (MVC) VC, yang merupakan implementasi yang cukup umum di OOP.Ambil contoh,
django.db.models.Model
kelas Django . Ketika kita melihatdjango.db.models.Model
objek, kita melihat Model meskipun itu sudah merupakan implementasi penuh dari MVC. Dengan asumsi MySQL adalah database back end:MySQLdb
adalah Model (lapisan penyimpanan data, dan logika bisnis mengenai cara berinteraksi dengan / memvalidasi data).django.db.models.query
adalah Controller (menangani input dari View dan menerjemahkannya untuk Model ).django.db.models.Model
adalah View (apa yang berinteraksi dengan pengguna).Interaksi ini sama dengan "pengembang sisi klien" Anda ketika bekerja dengan
yourproject.forms.YourForm
(mewarisi daridjango.forms.ModelForm
) objek:django.db.models.Model
, mereka perlu tahu cara berinteraksiyourproject.forms.YourForm
( Model mereka ).MySQLdb
, "pengembang sisi klien" Anda tidak perlu tahu apa-apa tentangyourproject.models.YourModel
.sumber