ORM-ul încorporat al Django are un câmp ManyToMany pe care îl puteți selecta. Cred că multi-selectorul implicit este o problemă, iar acest lucru a fost confirmat de mulți utilizatori finali care descriu modul în care selectorul îi face să greșească în timp ce editează acele câmpuri particulare. Aici voi descrie două lucruri. În primul rând, cum să schimbați widgetul câmpului respectiv cu ceva mai plăcut. În continuare voi descrie câteva blocaje la care ar trebui să aveți grijă să aveți grijă atunci când utilizați acest câmp cu ModelForms, mai ales în timpul salvării.

django

Cele mai multe relații sunt cel mai bine evitate dacă este posibil. Sunt dezordonate și forțează tot codul să gestioneze mai multe instanțe ale unei relații. O listă de ingrediente dintr-o masă ar putea fi reprezentată printr-o relație de mai multe persoane, cu excepția cazului în care doriți să reutilizați aceste ingrediente. Atunci ai două opțiuni; fie permite copierea, fie folosește un câmp de la mai mulți la mulți. Deoarece aceste ingrediente ar putea fi schimbate și acest lucru trebuie să se propage la toate mesele din care fac parte, am optat pentru ultima soluție.

Modele și codul formularului

Iată codul modelului de bază pentru mese, disponibil și ca model.py esențial.

Toate acestea sunt lucruri de modelare de bază. Ingredientele au un nume și relații cu dietele și preferințele alimentare. O masă poate avea multe ingrediente, un nume și un set de categorii de meniu. 1

Acum, să aruncăm o privire la formularul de adăugare/modificare a ingredientelor. Acesta este un ModelForm cu mai multe utilizări, disponibil și sub forma forms.py.

Toate lucrurile fanteziste se întâmplă în __init__. Inițializez un formular cu IngredientForm (brand = brand) pentru a configura filtrarea obiectelor FoodPreference și schimb widgeturile în CheckBoxSelectMultiple. Acest lucru se redă frumos ca un rând de casete de selectare în loc de multi-selectare stupidă.

Relații fanteziste M2M cu ModelForms

Ciudățenia începe atunci când încercăm să salvăm acest formular.

Acest lucru aruncă o eroare deoarece forma exclude în mod specific relația de franciză. Soluția standard ForeignKey este să folosiți commit = False și să o definiți singur.

Acest lucru funcționează fără erori vizibile, până când reveniți la acel obiect și observați că niciuna dintre relațiile M2M (Diet s și FoodPreference s) nu a fost salvată. De ce se întâmplă asta?

Un alt efect secundar al utilizării commit = False se observă atunci când modelul dvs. are o relație de la mulți la mulți cu un alt model. Dacă modelul dvs. are o relație de la mulți la mulți și specificați commit = False atunci când salvați un formular, Django nu poate salva imediat datele formularului pentru relația de la mulți la mulți. Acest lucru se datorează faptului că nu este posibil să salvați mai multe date pentru o instanță până când instanța nu există în baza de date.

Acesta este modul în care modifică codul.

Rețineți că save_m2m este apelat la vechiul obiect formular, nu obiectul model salvat.

Acest lucru ar trebui menționat mai bine în documentația Django. Abia după ce am săpat în modul de comitere = Funcții false, am găsit acest fragment.

Învelire

Modelele și ModelForm-urile Django sunt grozave, dar cu siguranță limitate în anumite aspecte. Odată ce stăpâniți elementele de bază, efectuarea unor modificări ușoare (ca aceasta) poate dura ceva timp pentru a vă da seama. Veștile bune sunt odată ce le faci, sunt ușoare și înveți mai multe.

Începeți să creați o listă de câmpuri Django personalizate, modele abstracte moștenite și câteva widget-uri noi pentru a face partea frontală mai frumoasă. Acest lucru vă va economisi timp mai târziu și vă va forța într-un model valoros de reutilizare a scrierii.

Acest lucru va fi schimbat cu un ForeignKey atunci când voi avea o șansă. ↩