我正在尝试尽可能多地使用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?
答案 0 :(得分: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
就个人而言,我更喜欢第一种方法,因为代码较少。