5

Допустит, у нас есть приложение под названием гардероб и она имеет некоторые модели:Джанго: 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, которая сможет обрабатывать данные по предварительно заполненным полям.

В частности, я хочу следующее поведение:

  1. Если я посещаю /closet/outfit/new Я хочу, чтобы получить стандартный ModelForm для Outfit модели со всем пустым, и все редактируемые.
  2. Если я нахожусь /closet/outfit/new/?shirt=1 Я хочу видеть все поля, которые я видел в случае 1), но я хочу, чтобы поле рубашки было заполнено рубашкой с pk = 1. Кроме того, я хочу, чтобы поле рубашки отображалось как не редактируемое. Если форма отправлена ​​и считается недействительной, когда форма снова отображается, я хочу, чтобы поле рубашки продолжало оставаться незаменимым.
  3. Если я нахожусь /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().

Две проблемы:

  1. Если я посещаю /closet/outfit/new/?awesomeness_rating=10 тогда моя форма предварительно заполняет с [u'10'] вместо того, чтобы просто заполнение 10. Есть ли фильтр, который я должен использовать в своем шаблоне или немного обработки, которую я могу добавить к моему представлению, чтобы сделать форматирование более подходящим?
  2. Если я хочу предварительно указать несколько кусочков головных уборов, то какой правильный формат передать то, что похоже на список 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 зайцев: числовая получает данные принуждают из юникода в числовой и разглаживает списки, когда это возможно (как предназначена). Необходимо проверить, работает ли это в многозначных полях.

ответ

4

Это self.request, где угодно в CBV. :-)

ОК, позвольте мне сделать этот ответ более полным. В принципе, вам нужен метод get_initial, который предоставляется FormMixin. Замените его, чтобы заполнить начальные значения для ваших полей.

+0

Это отличный первый шаг. У меня есть два вопроса о том, как это реализовать. Пожалуйста, ознакомьтесь с изменениями к первоначальному сообщению выше. Я думаю, что для своих целей я закончу этот маршрут, так как он получит суть. Но в той степени, в которой другие могут заботиться об исходной проблеме: есть ли у кого-то решение первоначального вопроса ... вместо того, чтобы просто заполнять форму исходными данными, есть ли способ отображения предварительно заполненных полей как заблокировано? – 8one6

+0

Один из способов - добавить атрибут 'readonly' к элементу ввода, возможно, в методе' get_form' представления. Вы можете взять поля 'request.GET' (или даже лучше использовать свой' get_initial', чтобы избежать дублирования кода) и изменить виджет каждого поля, имеющего там значение. –

+0

Спасибо. Я совершенно новичок в этом, и у меня все еще возникают проблемы с форматированием unicode. Я понимаю, что все записи в QueryDict, которые я получаю из 'request.GET', будут отформатированы как строки Unicode. Есть ли общий способ конвертировать unicode в свой собственный тип данных python? Поэтому, если я делаю '/ closet/outfit/new /? Awesomeness_level = 10', я хочу убедиться, что поле препопыляется с 10 вместо [u'10] ... – 8one6

 Смежные вопросы

  • Нет связанных вопросов^_^