1

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

我可能会过度思考或混淆自己。为了便于阅读,所有代码都被删减了

我们有一个库存系统,其中包含 PartNumbers(抽象)、Carriers(带有位置、序列号和数量编号的 PartNumbers 的实际实例)和移动,用于记录从库存中提取物品的时间、取走了多少以及它来自哪个 Carrier。

我想在 PartNumber 详细信息页面上有“提取库存”链接,然后将可用的承运人 ( pn.carrier_set.all() ) 自动填充到 MovementForm 上的 FK 下拉列表中。

模型.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 收集 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

视图.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'”错误-但我怀疑该错误是否准确反映了我做错了什么。

我一直使用这些帖子作为粗略的指导方针:

如何使用初始数据对 django 的通用 CreateView 进行子类化?

如何将 CreateView 与 ModelForm 一起使用

4

1 回答 1

1

如果我从我们的评论中正确理解了您,您所需要的只是更改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__,设置查询集:

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

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

于 2013-09-25T03:20:45.170 回答