Powiedzmy mamy aplikację o nazwie garderoba i ma kilka modeli:Django: CreateView z pre-zaludnionych i nieedytowalnych dziedzinach określonych przez ciąg kwerendy
# closet.models.py
class Outfit(models.Model):
shirt = models.ForeignKey(Shirt)
pants = models.ForeignKey(Trouser)
class Shirt(models.Model):
desc = models.TextField()
class Trouser(models.Model):
desc = models.TextField()
class Footwear(models.Model):
desc = models.TextField
Używanie zwykłych widok szczegółowy, to łatwo zrobić conf URL Aby uzyskać szczegółowe informacje na temat każdego z nich:
#urls.py
urlpatterns = patterns('',
url(r'^closet/outfit/(?P<pk>\d+)$', DetailView(model=Outfit), name='outfit_detail'),
url(r'^closet/shirt/(?P<pk>\d+)$', DetailView(model=Shirt), name='shirt_detail'),
url(r'^closet/trouser/(?P<pk>\d+)$', DetailView(model=Trouser), name='trouser_detail'),
url(r'^closet/footwear/(?P<pk>\d+)$', DetailView(model=Footwear), name='footwear_detail'),
)
Chciałbym teraz zdefiniować widoki, które utworzą nowy obiekt każdego typu. Chciałbym to zrobić z rozszerzoną wersją CreateView
, która będzie w stanie obsłużyć dane na wstępnie wypełnionych polach.
szczególności chcę następujące zachowanie:
- Gdybym odwiedzić
/closet/outfit/new
Chcę dostać standardowegoModelForm
dla modeluOutfit
we wszystko puste i wszystko edytowalne. - Jeśli odwiedzę
/closet/outfit/new/?shirt=1
, chcę zobaczyć wszystkie pola, które widziałem w przypadku 1), ale chcę, aby pole koszulki było wstępnie wypełnione koszulką z pk = 1. Dodatkowo chcę, aby pole koszulek było wyświetlane jako nierejestrowalne. Jeśli formularz zostanie przesłany i zostanie uznany za nieważny, przy ponownym wyświetlaniu formularza chcę, aby pole koszulek było nadal nie do edycji. - Jeśli odwiedzę
/closet/outfit/new/?shirt=1&trouser=2
, chcę zobaczyć wszystkie pola, które widziałem w przypadku 1), ale teraz zarówno koszula, jak i spodnie powinny być wstępnie przygotowane i nie nadające się do edycji. (Tj. Tylko polefootwear
powinno być edytowalne.)
Generalnie jest to możliwe? To znaczy. czy querystring może w ten sposób modyfikować strukturę wyświetlanego formularza? Chcę to osiągnąć w możliwie najdrobniejszy sposób. Moje jelito mówi mi, że to powinno być wykonalne z poglądami opartymi na klasach i być może wymagałoby to model_form_factory
, ale nie mogę uzyskać logiki prosto w mojej głowie. W szczególności nie byłem pewien, czy możliwe było uzyskanie dostępu opartego na klasach do parametrów request.REQUEST
(tj. request.POST
lub request.GET
) w czasie, gdy konstruowany jest ModelForm
.
Być może jest to możliwe tylko wtedy, gdy dla zablokowanych pól używam różnych słów kluczowych z zapytaniami. To znaczy. być może adres URL musi być: /closet/outfit/new/?lock_shirt=1
i /closet/outfit/new?lock_shirt=1&lock_trouser=2
. Być może, jeśli zrobi się to w ten sposób, handler POST
otrzyma zarówno listę zablokowanych pól (dla celów wyświetlania formularza w przeglądarce), jak i regularną listę wszystkich pól modelu w celu rzeczywistego utworzenia obiektu.
Dlaczego chcę to: W szablonie dla footwear_detail
chciałbym być w stanie dokonać takiego znacznika
<a href="{% url outfit_new %}?footwear={{object.pk}}>Click to create a new outfit with this footwear!</a>
W ogóle, to byłoby bardzo przydatne, aby móc tworzyć linki do formularzy których "struktura" (nie tylko wartości) zmienia się w zależności od przekazanego zapytania.
Odpowiadając na wielką sugestią BERISLAV Lopac:
Więc poszedł do przodu i tak:
class CreateViewWithPredefined(CreateView):
def get_initial(self):
return self.request.GET
To dostaje mi 90% tego, co mi potrzeba. Ale pozwól mi nieco poprawić sytuację.Załóżmy, że dodaję dwa pola do modelu Strój: headgear = models.ManyToManyField('headgear')
i awesomeness_rating = models.FloatField()
.
dwa problemy:
- Gdybym odwiedzić
/closet/outfit/new/?awesomeness_rating=10
następnie moja forma wstępnie uzupełniane[u'10']
zamiast po prostu wypełnienie10
. Czy jest jakiś filtr, którego powinienem użyć w moim szablonie lub trochę przetwarzania mogę dodać do mojego widoku, aby formatowanie było bardziej odpowiednie? - Jeśli chcę wstępnie określić kilka części nakrycia głowy, jaki jest odpowiedni format do przekazania czegoś, co wydaje się być listą pythonów w ciągu zapytania? To znaczy. powinienem zrobić
/closet/outfit/new/?headgear=1,2,3
? Jeśli tak, to czy Django poprawnie się zorientuje, że chciałbym wstępnie wybrać 3 części nakryć głowy z tymi identyfikatorami?
kontynuowania pracy na tym ...
class CreateViewWithPredefined(CreateView):
def get_initial(self):
initial = super(CreateView, self).get_initial()
for k, v in self.request.GET.iterlists():
if len(v) > 1:
initial.update({ k : v })
else:
initial.update({ k : v[0] })
return initial
Wydaje się zabić 2 pieczenie na jednym ogniu: Dane liczbowe zostaje zmuszony z Unicode do numerycznego i spłaszcza list, jeśli to możliwe (jak zamierzony). Musisz sprawdzić, czy to działa na polach wielowartościowych.
To świetny pierwszy krok. Mam dwa pytania dotyczące sposobu wdrożenia tego. Zobacz zmiany w oryginalnym wpisie powyżej. Myślę, że dla moich celów, skończę tę drogę, ponieważ jest to najważniejsze. Ale w takim stopniu, w jakim inni mogą się przejmować pierwotnym problemem: czy ktoś ma rozwiązanie pierwotnego pytania ... zamiast po prostu wypełniać formularz danymi początkowymi, czy istnieje sposób, aby wstępnie wypełnione pola faktycznie wyświetlały się jako zamknięty? – 8one6
Jednym ze sposobów jest dodanie atrybutu 'readonly' do elementu input, być może w metodzie' get_form' widoku. Możesz pobrać pola 'request.GET' (lub jeszcze lepiej użyć' get_initial' w celu uniknięcia duplikacji kodu) i zmodyfikować widget każdego pola, które ma tam wartość. –
Dzięki. Jestem całkiem nowy w tym i nadal mam problemy z formatowaniem Unicode. Rozumiem, że wszystkie wpisy w QueryDict, które otrzymam z 'request.GET' będą sformatowane jako ciągi Unicode. Czy istnieje ogólny sposób konwertowania unicode na jego macierzysty typ danych python? Więc jeśli robię '/ closet/outfit/new /? Awesomeness_level = 10', chcę się upewnić, że pole wstępnie wypełni się 10 zamiast [u'10] ... – 8one6