#django #django-templates #django-forms
#django #django-templates #django-forms
Вопрос:
У меня есть эти модели:
OrderLine
StockItem
WaybillItem
Waybill
Waybill
Состоит из нескольких WaybillItem
, связанных с одним номером заказа.
WaybillItem
Состоит из OrderLine
amp; a StockItem
Отношение между StockItem
amp; Orderline
является свободным многие ко многим, зависящим от запроса из данных 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
Это должно привести к выпадающему списку для waybillline для waybill с номером 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_ID
amp; Stock_ID
, но пользователь использует только один выпадающий список.
Я использую inlineformset_factory
для создания списка строк wabill.
Кто-нибудь может помочь?
Отредактировано добавление представления моделей и шаблона
Модели: накладная
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()
Это WaybillItem
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>
Комментарии:
1. Как правило, более полезно включать упрощенную версию кода, который вы используете для своих моделей, вместо перечисления их взаимосвязей.
2. там, где выпадающие списки являются динамическими, я использую jQuery для управления списками. На мой взгляд, это быстрее и понятнее. Вот ссылка для начала: webcloud.se/log/AJAX-in-Django-with-jQuery Также начал использовать шаблоны jQuery для форматирования, а не делать это в django.
Ответ №1:
Прежде всего, вам следует провести рефакторинг ваших моделей. Создать хранилище моделей:
class WareHouse(models.Model):
code = models.CharField...
Свяжите OrderItem и StockItem со складом с помощью внешних ключей вместо ‘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