Допустит, у нас есть приложение под названием гардероб и она имеет некоторые модели:Джанго: CreateView с предварительно заселенными и нередактируемыми полей, задаваемых строкой запроса
# 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
Используя общий вид детали, это легко сделать URL конф Подробную информацию о каждом из них:
#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'),
)
То, что я хотел бы сделать дальше, определить виды, которые будут создавать новый объект каждого типа. Я хотел бы сделать это с расширенной версией CreateView
, которая сможет обрабатывать данные по предварительно заполненным полям.
В частности, я хочу следующее поведение:
- Если я посещаю
/closet/outfit/new
Я хочу, чтобы получить стандартныйModelForm
дляOutfit
модели со всем пустым, и все редактируемые. - Если я нахожусь
/closet/outfit/new/?shirt=1
Я хочу видеть все поля, которые я видел в случае 1), но я хочу, чтобы поле рубашки было заполнено рубашкой с pk = 1. Кроме того, я хочу, чтобы поле рубашки отображалось как не редактируемое. Если форма отправлена и считается недействительной, когда форма снова отображается, я хочу, чтобы поле рубашки продолжало оставаться незаменимым. - Если я нахожусь
/closet/outfit/new/?shirt=1&trouser=2
Я хочу видеть все поля, которые я видел в случае 1), но теперь поля рубашки и брюк должны быть предварительно покрыты и неотредактированы. (I. только полеfootwear
должно быть доступно для редактирования.)
В целом, возможно ли это? То есть может ли строка запроса изменить структуру отображаемой формы таким образом? Я хочу сделать это самым DRYest способом. Моя кишка говорит мне, что это должно быть выполнимо с учетом класса и, возможно, будет связано с model_form_factory
, но я не могу получить логику прямо в своем уме. В частности, я не был уверен, можно ли получить доступ к классу request.REQUEST
(то есть параметры request.POST
или request.GET
) в момент построения ModelForm
.
Возможно, это возможно только в том случае, если для заблокированных полей используются разные ключевые слова с запросом. То есть возможно, URL-адрес должен быть: /closet/outfit/new/?lock_shirt=1
и /closet/outfit/new?lock_shirt=1&lock_trouser=2
. Возможно, если бы это было сделано так, то обработчик POST
получил бы список заблокированных полей (для отображения формы в браузере) вместе с регулярным списком всех полей модели для фактического создания объекта.
Почему я хочу это: В шаблоне для footwear_detail
я хотел бы быть в состоянии сделать тег как
<a href="{% url outfit_new %}?footwear={{object.pk}}>Click to create a new outfit with this footwear!</a>
В общем, было бы очень полезно, чтобы иметь возможность сделать ссылки на формы чья «структура» (а не только значения) изменяется в зависимости от пройденного запроса.
В ответ на большое предложение от Берислав Lopac:
Так что я пошел вперед и сделал:
class CreateViewWithPredefined(CreateView):
def get_initial(self):
return self.request.GET
Это заставляет меня 90% того, что мне нужно. Но позвольте мне сформулировать ситуацию немного больше.Скажем, я добавляю два поля в модель Outfit: headgear = models.ManyToManyField('headgear')
и awesomeness_rating = models.FloatField()
.
Две проблемы:
- Если я посещаю
/closet/outfit/new/?awesomeness_rating=10
тогда моя форма предварительно заполняет с[u'10']
вместо того, чтобы просто заполнение10
. Есть ли фильтр, который я должен использовать в своем шаблоне или немного обработки, которую я могу добавить к моему представлению, чтобы сделать форматирование более подходящим? - Если я хочу предварительно указать несколько кусочков головных уборов, то какой правильный формат передать то, что похоже на список python, через строку запроса? То есть должен ли я делать
/closet/outfit/new/?headgear=1,2,3
? Если да, будет ли Django правильно выяснить, что я хотел бы предварительно выбрать 3 части головных уборов с этими ID?
Продолжая работать над этим ...
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
Это, кажется, убить 2 зайцев: числовая получает данные принуждают из юникода в числовой и разглаживает списки, когда это возможно (как предназначена). Необходимо проверить, работает ли это в многозначных полях.
Это отличный первый шаг. У меня есть два вопроса о том, как это реализовать. Пожалуйста, ознакомьтесь с изменениями к первоначальному сообщению выше. Я думаю, что для своих целей я закончу этот маршрут, так как он получит суть. Но в той степени, в которой другие могут заботиться об исходной проблеме: есть ли у кого-то решение первоначального вопроса ... вместо того, чтобы просто заполнять форму исходными данными, есть ли способ отображения предварительно заполненных полей как заблокировано? – 8one6
Один из способов - добавить атрибут 'readonly' к элементу ввода, возможно, в методе' get_form' представления. Вы можете взять поля 'request.GET' (или даже лучше использовать свой' get_initial', чтобы избежать дублирования кода) и изменить виджет каждого поля, имеющего там значение. –
Спасибо. Я совершенно новичок в этом, и у меня все еще возникают проблемы с форматированием unicode. Я понимаю, что все записи в QueryDict, которые я получаю из 'request.GET', будут отформатированы как строки Unicode. Есть ли общий способ конвертировать unicode в свой собственный тип данных python? Поэтому, если я делаю '/ closet/outfit/new /? Awesomeness_level = 10', я хочу убедиться, что поле препопыляется с 10 вместо [u'10] ... – 8one6