Django CBV表格预先填充的外键数据集

时间:2013-09-25 00:57:22

标签: django django-forms django-views

我正在尝试尽可能多地使用CBV,并希望在基于generic.CreateView的ModelForm中预先填充数据,并通过URL传入一些数据。

我可能会过度思考或混淆自己。所有代码都删除了易读性

我们有一个库存系统,包括PartNumbers(抽象),运营商(PartNumbers的实际实例,包括位置,序列号和数量)和从库存中提取物品时的记录移动,采取的数量以及它来自的载体。

我想在PartNumber详细信息页面上找到“提取清单”链接,然后将可用的运营商(pn.carrier_set.all())自动填入MovementForm的FK下拉列表中。

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 中,我通过网址收集PartNumber为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

1 个答案:

答案 0 :(得分:1)

如果我从评论中正确理解您,您只需更改MovementForm的运营商字段的查询集即可设置可用选项。在这种情况下,我会使用get_initialget_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__中,设置查询集:

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

就个人而言,我更喜欢第一种方法,因为代码较少。