Я получаю ошибку 'Выберите правильный выбор. Этот выбор не является одним из доступных при попытке отправить ModelForm. Хотя значения, передаваемые из внешнего интерфейса, выглядят корректными (PK для каждого) и все необходимые значения предоставляются, но он все равно не возвращает мне очищенных данных
Я все еще новичок в Django и поиск в Google не дал мне результатов, которые работают
(также я использую хрустящие формы для оформления внешнего интерфейса)
forms.py
code = forms.CharField(required=True)
itemtype = forms.ModelChoiceField(required=True, queryset=ItemType.objects.all())
location = forms.ModelChoiceField(required=True, queryset=Location.objects.all())
parent = forms.ModelChoiceField(required=False, queryset=Item.objects.all())
class Meta:
model = Item
fields = ['code', 'itemtype', 'location', 'parent']
def __init__(self, *args, **kwargs):
super(CreateItemWithParentForm, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].widget.attrs = {'class': 'form-control'}
self.fields['itemtype'].label_from_instance = lambda obj: "{0}".format(obj.name)
self.fields['location'].label_from_instance = lambda obj: "{0}".format(obj.address)
self.fields['parent'].label_from_instance = lambda obj: "{0}".format(obj.code)
self.helper = FormHelper(self)
self.helper.form_show_labels = True
self.helper.form_id = 'createitemform'
self.helper.layout = Layout(
Fieldset("Create New Item",
Field('code', css_class="mt-2", placeholder="Code", name="code", id="code"),
Field('itemtype', css_class="mt-2", name="itemtype", placeholder="Item type", css_id="itemtype"),
Field('location', css_class="mt-2", name="location", placeholder="Location", css_id="location"),
Field('parent', css_class="mt-2", name="parent", placeholder="Parent Item", css_id="parent"),
Button('createitemformbutton', 'Submit', css_class="btn-light"),
css_class='border',
)
)
views.py
class CreateItemWithParent(FormView):
"""
create a new item with specified parent
"""
template_name = 'add_item.html'
form_class = CreateItemWithParentForm
success_url = reverse_lazy('add_item_success')
def get_initial(self):
return {"pk": self.kwargs.get('pk')}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
...
return context
def clean_itemtype(self):
data = self.cleaned_data['itemtype']
return data
def clean_location(self):
data = self.cleaned_data['location']
return data
def clean_parent(self):
data = self.cleaned_data['parent']
return data
def form_valid(self, form):
return super().form_valid(form)
def save_new_item_with_parent(request):
options = {}
if request.method == 'POST':
item_form = CreateItemWithParentForm(request.POST)
if item_form.is_valid():
child = _add_item(item_form.cleaned_data['code'], int(item_form.cleaned_data['itemtype']), int(item_form.cleaned_data['location']))
parent = item_form.cleaned_data['parent']['id']
if child != -1:
if parent != "-1":
if _add_itemitem(int(parent), int(child)):
options['success'] = True
else:
options['success'] = False
else:
options['success'] = True
else:
options['success'] = False
else:
print('form not valid')
print(item_form.errors)
return JsonResponse(options)
class Meta:
model = Item
fields = ['code', 'itemtype', 'location', 'parent']
def __init__(self, *args, **kwargs):
super(CreateItemWithParentForm, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].widget.attrs = {'class': 'form-control'}
self.fields['itemtype'].label_from_instance = lambda obj: "{0}".format(obj.name)
self.fields['location'].label_from_instance = lambda obj: "{0}".format(obj.address)
self.fields['parent'].label_from_instance = lambda obj: "{0}".format(obj.code)
self.helper = FormHelper(self)
self.helper.form_show_labels = True
self.helper.form_id = 'createitemform'
self.helper.layout = Layout(
Fieldset("Create New Item",
Field('code', css_class="mt-2", placeholder="Code", name="code", id="code"),
Field('itemtype', css_class="mt-2", name="itemtype", placeholder="Item type", css_id="itemtype"),
Field('location', css_class="mt-2", name="location", placeholder="Location", css_id="location"),
Field('parent', css_class="mt-2", name="parent", placeholder="Parent Item", css_id="parent"),
Button('createitemformbutton', 'Submit', css_class="btn-light"),
css_class='border',
)
)
models.py
class ItemType(models.Model):
name = models.TextField(default='')
start = models.DateTimeField(null=True)
description = models.TextField(default='')
history = HistoricalRecords()
def __str__(self):
return self.id
class Location(models.Model):
name = models.TextField(default='')
address = models.TextField(default='')
history = HistoricalRecords()
def __str__(self):
return self.id
class Item(models.Model):
ITEMTYPE_CHOICES = ItemType.objects.values('id', 'name')
LOCATION_CHOICES = Location.objects.values('id', 'address')
# children = models.ManyToManyField('Item', through='ItemItem')
code = models.TextField(default='')
itemtype = models.ForeignKey('ItemType', on_delete=DO_NOTHING, choices=ITEMTYPE_CHOICES)
location = models.ForeignKey('Location', on_delete=DO_NOTHING, choices=ITEMTYPE_CHOICES)
created = models.DateTimeField(null=True, auto_now=True)
edited = models.DateTimeField(null=True, auto_now=True)
history = HistoricalRecords()
HTML шаблон (с Jquery)
<section class="container-fluid" id="home">
<section class="container-fluid" id="intro_text">
<h2>Add Item</h2>
<div class="row">
<div id="mainpane" class="col-md-12">
<div class="dd" id="success"></div>
{% csrf_token %}
{% crispy form %}
</div>
</div>
</section>
</section>
<script type="text/javascript">
$(document).ready(function(){
$("#button-id-createitemformbutton").on("click", function(){
$.ajax({
url : "{% url "save_new_item_with_parent" %}",
type : "POST",
data: $("#createitemform").serialize(),
dataType: 'json',
success: function(result) {
if(result.success){
$("#success").html('Your item has been recorded in the database. <a href="/item/list/">View all items?</a>');
$("#success").removeClass('dd');
// reset form
$("#code").val('');
$("#id_itemtype").val(1);
$("#id_location").val(1);
if(window.location.pathname.length < 11){
$("#id_parent").val(-1);
}
}
if(!result.success){
alert(result.errors);
}
},
});
});
});
</script>