2013-09-25 5 views
1

Я стараюсь как можно больше использовать CBV и хочу предварительно заполнять данные в ModelForm на основе generic.CreateView с некоторыми данными, передаваемыми через URL.Django CBV Forms preopulated external key dataset

Возможно, я передумал или смутил себя. Весь код, сокращенный для удобочитаемости

У нас есть система инвентаризации с PartNumbers (абстракциями), несущие (фактические экземпляры PartNumbers с указанием местоположения, серийные номера и количества) и Движения для записи, когда элементы извлекаются из инвентаря, сколько взято и от какого Перевозчика он пришел.

Я хотел бы иметь ссылку «извлечения инвентаря» на странице подробных сведений PartNumber, а затем добавить доступные несущие (pn.carrier_set.all()) в поле FK в MovementForm.

models.py

class PartNumber(models.Model): 
    name = models.CharField("Description", max_length=100) 
    supplier_part_number = models.CharField(max_length=30, unique=True) 
    slug = models.SlugField(max_length=40, unique=True) 

class Carrier(models.Model): 
    part_numbers = models.ForeignKey(PartNumber) 
    slug = models.SlugField(max_length=10, unique=True, blank=True, editable=False) 
    location = models.ForeignKey(Location) 
    serial_number = models.CharField(max_length=45, unique=True, null=True, blank=True) 
    qty_at_new = models.IntegerField() 
    qty_current = models.IntegerField() 

class Movement(models.Model): 
    carrier = models.ForeignKey(Carrier) 
    date = models.DateField(default=timezone.now()) 
    qty = models.IntegerField() 

Я играл с get_initial() и get_form_kwargs() без успеха:

В urls.py Я собираю партномер через URL, как pn_slug

url(r'^partnumber/(?P<pn_slug>[-\w]+)/extract/$', views.MovementCreate.as_view(), name='pn_extract'), 

forms.py является общим

class MovementForm(forms.ModelForm): 
    class Meta: 
    model = Movement 

views.py

class MovementCreate(generic.CreateView): 
    form_class = MovementForm 
    model = Movement 

    def get_form_kwargs(self): 
    kwargs = super(MovementCreate, self).get_form_kwargs() 
    kwargs['pn_slug'] = self.request.POST.get("pn_slug") 
    return kwargs 

    # here we get the appropriate part and carrier and. 
    # return it in the form 
    def get_initial(self): 
    initial = super(MovementCreate, self).get_initial() 
    # this didn't work, hence using get_form_kwargs 
    #pn = PartNumber.objects.get(slug=self.request.POST.get("pn_slug")) 
    pn = PartNumber.objects.get(slug=self[pn_slug]) 
    carriers = pn.carrier_set.all() 
    initial['carrier'] = carriers 
    return initial 

Как она стоит, я получаю «глобальное имя„pn_slug“не определен» ошибки - но я сомневаюсь, что ошибка точно отражает то, что Я поступил неправильно.

Я использую эти сообщения как грубые рекомендации:

How to subclass django's generic CreateView with initial data?

How do I use CreateView with a ModelForm

+0

Я немного смущен вашим процессом. Эта форма создания для «Движения» или формы для создания «PartNumber»? Вы устанавливаете модель в «Движение», но затем вы устанавливаете исходные данные как «PartNumber». ('pn = PartNumber.objects.get (slug = self [pn_slug]) ') – jproffitt

+0

Хорошо, две вещи. --- 1. Я создаю Движение из Части. Из Части мы получаем Перевозчика. В MovementCreateView мы хотим, чтобы Carrier FK был подмножеством всех Перевозчиков (на основе PartNumber). Итак, мы получаем объект детали из slug, затем получаем список доступных носителей через pn.carrier_set.all(), затем мы отправляем этот список несущих в ModelForm для Movement. --- 2. У меня есть часть этой работы - я должен использовать р = PartNumber.objects.get (пули = self.kwargs [ "pn_slug"]) в get_initial() – datakid

+0

Так, по существу я m ищет способ изменить набор запросов, используемый FK в форме. – datakid

ответ

1

Если я вас правильно понял из наших замечаний, все, что вам нужно просто изменить QuerySet в MovementForm ' чтобы установить доступные параметры. В этом случае я бы использовал get_initial или get_form_kwargs. Вместо этого я хотел бы сделать это в get_form:

def get_form(self, *args, **kwargs): 
    form = super(MovementCreate, self).get_form(*args, **kwargs) 

    pn = PartNumber.objects.get(slug=self.kwargs['pn_slug']) 
    carriers = pn.carrier_set.all() 

    form.fields['carrier'].queryset = carriers 
    return form 

Другой способ сделать это было бы использовать get_form_kwargs:

def get_form_kwargs(self): 
    kwargs = super(MovementCreate, self).get_form_kwargs() 
    kwargs['pn_slug'] = self.kwargs.get("pn_slug") 
    return kwargs 

Затем в форму-х __init__ установите QuerySet:

class MovementForm(forms.ModelForm): 
    class Meta: 
    model = Movement 

    def __init__(self, *args, **kwargs): 
     pn_slug = kwargs.pop('pn_slug') 
     super(MovementForm, self).__init__(*args, **kwargs) 

     pn = PartNumber.objects.get(slug=pn_slug) 
     carriers = pn.carrier_set.all() 

     self.fields['carrier'].queryset = carriers 

Лично я бы предпочел первый метод, так как он меньше кода.

+0

Perfect - обработано. Спасибо @jproffitt – datakid