你如何有一个选择来选择两个不同的松散相关的模型在一个 django 形式



我有这些模型:

OrderLine
StockItem
WaybillItem
Waybill

Waybill由连接到一个订单号的多个WaybillItem组成。

WaybillItemOrderLineStockItem组成StockItemOrderline 之间的关系是一个松散的多对多,依赖于OrderLine数据的查询:

 StockItem.objects.filter( wh_code = OrderLine.origin_wh_code ).filter( si_code = OrderLine.si_code ).filter( commodity_code = OrderLine.commodity_code )

在表单中,我希望用户有一个选择来选择可能的选项,其中每个匹配的StockItem/OrderLine都有一个项目。

例:在OrderLines有以下OrderLines

Line_ID, OrderNumber, commodity_code, si_code, origin_wh_code
1001,1, Wheat, 2222,Rome
1002,1, Oat, 2222, Rome
1003,2, Oat, 2222, Rome

StockItem,您有:

Stock_ID, commodity_code, si_code, wh_code, reference_code
10, Wheat, 2222, Rome, 222201
12, Oat, 2222, Rome, 222202
13, Wheat, 2222, Rome, 222203
14, Wheat, 2222, Paris, 222203

这应该会导致编号为 1 的运单的运单线下拉列表,其中:

Line_ID, Stock_ID, (commodity_code, si_code, reference_code)
1001,  10, (Wheat, 2222, 222201 
1001,  13, (Wheat, 2222, 222203)
1002,  12, (Oat,2222, 222202)

选中后,Waybill行应同时保存Line_IDStock_ID,但用户仅使用单个下拉列表。我正在使用inlineformset_factory来创建瓦比尔行列表。

谁能帮忙?

已编辑添加模型视图和模板

模型:运单

class Waybill( models.Model ):
    ltiNumber = models.CharField( max_length = 20 )
    waybillNumber = models.CharField( max_length = 20 )
    dateOfLoading = models.DateField( null = True, blank = True )
    recipientLocation = models.CharField( max_length = 100, blank = True )
    destinationWarehouse = models.ForeignKey( Places, blank = True )

教团

class OrderLine( models.Model ):
    lti_pk = models.CharField( max_length = 50, primary_key = True, db_column = 'LTI_PK' )
    lti_id = models.CharField( max_length = 40, db_column = 'LTI_ID' )
    code = models.CharField( max_length = 40, db_column = 'CODE' )
    origin_wh_code = models.CharField( max_length = 13, blank = True, db_column = 'ORIGIN_WH_CODE' )
    destination_location_code = models.CharField( max_length = 10, db_column = 'DESTINATION_LOCATION_CODE' )
    si_code = models.CharField( max_length = 8, db_column = 'SI_CODE' )
    commodity_code = models.CharField( max_length = 18, db_column = 'COMMODITY_CODE' )
    number_of_units = models.DecimalField( max_digits = 7, decimal_places = 0, db_column = 'NUMBER_OF_UNITS' )

这是库存模型

class StockItem( models.Model ):
        wh_pk = models.CharField( max_length = 90, blank = True, primary_key = True )
        wh_code = models.CharField( max_length = 13 )
        wh_name = models.CharField( max_length = 50, blank = True )
        si_code = models.CharField( max_length = 8 )
        origin_id = models.CharField( max_length = 23 )
        commodity_code = models.CharField( max_length = 18 )
        number_of_units = models.IntegerField()

这是运单项目

class WaybillItem( models.Model ):
        wbNumber = models.ForeignKey( Waybill )
        siNo = models.ForeignKey( OrderLine )
        coi_code = models.ForeignKey( StockItem )
        numberUnitsLoaded = models.DecimalField( default = 0, blank = False, null = False, max_digits = 10, decimal_places = 3 )

视图:

def waybillCreate( request, lti_code ):
   #Retrive the LTIs for this Waybill
   current_lti = OrderLine.objects.filter( code = lti_code )
    for lti in current_lti:
        c_sis.append( lti.si_code )
    current_stock = StockItem.in_stock_objects.filter( si_code__in = c_sis ).filter( wh_code = current_lti[0].origin_wh_code )
    class LoadingDetailDispatchForm( ModelForm ):
        #Here are the order lines
        siNo = ModelChoiceField( queryset = current_lti, label = 'Commodity' )
        #This is from the Stock
        coi_code = ModelChoiceField( queryset = current_stock )
        overload = forms.BooleanField( required = False )
        class Meta:
            model = LoadingDetail
            fields = ( 'siNo', 'numberUnitsLoaded', 'wbNumber', 'overloadedUnits', 'overOffloadUnits' , 'coi_code' )
    LDFormSet = inlineformset_factory( Waybill, LoadingDetail, form = LoadingDetailDispatchForm, fk_name = "wbNumber", formset = BaseLoadingDetailFormFormSet, extra = 5, max_num = 5 )
    current_wh = ''
    if request.method == 'POST':
        form = WaybillForm( request.POST )
        form.fields["destinationWarehouse"].queryset = Places.objects.filter( geo_name = current_lti[0].destination_loc_name )
        formset = LDFormSet( request.POST )
        if form.is_valid() and formset.is_valid():
            wb_new = form.save()
            instances = formset.save( commit = False )
            wb_new.waybillNumber = new_waybill_no( wb_new )
            for subform in instances:
                subform.wbNumber = wb_new
                subform.save()
            wb_new.save()
            return HttpResponseRedirect( '../viewwb/' + str( wb_new.id ) )
        else:
            loggit( formset.errors )
            loggit( form.errors )
            loggit( formset.non_form_errors )
    else:
        qs = Places.objects.filter( geo_name = current_lti[0].destination_loc_name ).filter( organization_id = current_lti[0].consegnee_code )
        if len( qs ) == 0:
            qs = Places.objects.filter( geo_name = current_lti[0].destination_loc_name )
        else:
            current_wh = qs[0]
        form = WaybillForm( 
            initial = {
                    'dispatcherName':      request.user.profile.compasUser.person_pk,
                    'dispatcherTitle':      request.user.profile.compasUser.title,
                    'ltiNumber':         current_lti[0].code,
                    'dateOfLoading':     datetime.date.today(),
                    'dateOfDispatch':    datetime.date.today(),
                    'recipientLocation': current_lti[0].destination_loc_name,
                    'recipientConsingee':current_lti[0].consegnee_name,
                    'transportContractor': current_lti[0].transport_name,
                    'invalidated':'False',
                    'destinationWarehouse':current_wh,
                    'waybillNumber':'N/A'
                }
        )
        form.fields["destinationWarehouse"].queryset = qs
        formset = LDFormSet()
    return render_to_response( 'waybill/createWaybill.html', {'form': form, 'lti_list':current_lti, 'formset':formset}, context_instance = RequestContext( request ) )

模板(部分(:

<table cellpadding="1px" cellspacing="1px" id="example" style="border:1px;">
    <thead>
        <tr><th></th><th>Commodity</th><th>{%if lti_list.0.is_bulk%}Metric Tons{%else%}Number of Units{%endif%}</th><th>Overload</th></tr>
    </thead>
    {% for sform in formset.forms %}
    <tr>
        <td>{{ sform.id }}{{forloop.counter}}</td>
        <td>{{ sform.siNo }} {{sform.coi_code}}</td>
        <td>{{ sform.numberUnitsLoaded }} {%for error in sform.numberUnitsLoaded.errors%}<span class='error'> {{error|escape}}</span>{%endfor%}</td>
        <td>{{ sform.overloadedUnits}}</td>
    </tr>
    {% endfor %}
</table>

首先,你应该重构你的模型。创建模型仓库:

class WareHouse(models.Model): 
     code = models.CharField...

使用外键而不是"origin_wh_code"和"wh_code"将订单项和库存项链接到仓库。只有这样,您才能使用联接选择数据。

将选项字段与自定义选项一起使用,甚至更好 - 创建从表单继承的内容。TypedChoiceField 字段,用于封装序列化(库存物料、订单项(pks 的逻辑。

choices = StockItem.objects.filter(commodity_code=F("warehouse__orders__commodity_code"))
        .values('pk', 'warehouse__orders__pk')# or , <other required fields>)
item = CustomChoiceField(choices= choices, required=True)

发布后,您可以检索对:

stock_item, order_item = form.cleaned_data['item']
#Save'em here

最新更新