Make progress with automatic form field for model autocompletion
This commit is contained in:
parent
258fd1747c
commit
a0775a69ca
@ -3,15 +3,56 @@ from django.forms import widgets
|
||||
from django.core.exceptions import ValidationError
|
||||
from parts import models as parts_models
|
||||
from shimatta_modules.EngineeringNumberConverter import EngineeringNumberConverter
|
||||
import uuid
|
||||
|
||||
class AutoCompleteWidget(widgets.Input):
|
||||
template_name = 'widgets/autocomplete-foreign-key.html'
|
||||
|
||||
def __init__(self, api_search_url, image_field_name, foreign_model, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.image_field_name = image_field_name
|
||||
self.foreign_model = foreign_model
|
||||
self.api_search_url = api_search_url
|
||||
|
||||
def get_context(self, name, value, attrs):
|
||||
context = super().get_context(name, value, attrs)
|
||||
try:
|
||||
instance = self.foreign_model.objects.get(id=uuid.UUID(value))
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
instance = None
|
||||
|
||||
image = None
|
||||
if instance is not None:
|
||||
image = getattr(instance, self.image_field_name)
|
||||
|
||||
|
||||
class AutoCompleteWidget(widgets.TextInput):
|
||||
template_name = 'widgets/autrocomplete-foreign-key.html'
|
||||
context['custom'] = {
|
||||
'search_url': self.api_search_url,
|
||||
'image_field_name': self.image_field_name,
|
||||
'current_instance': instance,
|
||||
'image': image,
|
||||
}
|
||||
return context
|
||||
|
||||
|
||||
class AutocompleteForeingKeyField(forms.UUIDField):
|
||||
def __init__(self, foreign_model=None, api_search_url=None, autocomplete_media_div=False, **kwargs):
|
||||
kwargs['widget'] = AutoCompleteWidget
|
||||
def __init__(self, foreign_model=None, api_search_url=None, image_field_name='image', **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.widget = AutoCompleteWidget(api_search_url, image_field_name, foreign_model)
|
||||
self.foreign_model = foreign_model
|
||||
|
||||
|
||||
def clean(self, value):
|
||||
pre_cleaned_uuid = super().clean(value)
|
||||
if pre_cleaned_uuid is None and not self.required:
|
||||
return None
|
||||
try:
|
||||
obj = self.foreign_model.objects.get(id=pre_cleaned_uuid)
|
||||
except self.foreign_model.DoesNotExist:
|
||||
raise ValidationError('Given element does not exist')
|
||||
return obj
|
||||
|
||||
|
||||
class MyTestForm(forms.Form):
|
||||
pass
|
||||
@ -118,8 +159,9 @@ class AddStockForm(forms.Form):
|
||||
new_stock.save()
|
||||
|
||||
class ComponentForm(forms.ModelForm):
|
||||
manufacturer = AutocompleteForeingKeyField(widget=AutoCompleteWidget)
|
||||
component_type = AutocompleteForeingKeyField()
|
||||
manufacturer = AutocompleteForeingKeyField(api_search_url='foo', foreign_model=parts_models.Manufacturer)
|
||||
component_type = AutocompleteForeingKeyField(api_search_url='bar', foreign_model=parts_models.ComponentType, required=False, image_field_name=None)
|
||||
package = AutocompleteForeingKeyField(api_search_url='pkgurl', foreign_model=parts_models.Package, required=False)
|
||||
class Meta:
|
||||
model = parts_models.Component
|
||||
fields = '__all__'
|
||||
|
@ -521,7 +521,7 @@ class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
|
||||
context['edit_form'] = EditComponentForm(instance=self.object)
|
||||
|
||||
context['stocks'] = Stock.objects.filter(component=self.object)
|
||||
context['comp_form'] = ComponentForm()
|
||||
context['comp_form'] = ComponentForm(instance=self.object)
|
||||
|
||||
return context
|
||||
|
||||
@ -546,10 +546,25 @@ class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
|
||||
context['edit_form'] = form
|
||||
return self.render_to_response(context)
|
||||
|
||||
def handle_submit_edit_component_post(self, request, **kwargs):
|
||||
context = self.get_context_data(**kwargs)
|
||||
|
||||
cform = ComponentForm(instance=self.object, data=request.POST, files=request.FILES)
|
||||
if cform.is_valid():
|
||||
print('valid')
|
||||
cform.save()
|
||||
else:
|
||||
print('invalid')
|
||||
context['comp_form'] = cform
|
||||
|
||||
return self.render_to_response(context)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
if 'submit-edit-comp' in request.POST:
|
||||
return self.handle_submit_edit_post(request, **kwargs)
|
||||
if 'submit-edit-component' in request.POST:
|
||||
return self.handle_submit_edit_component_post(request, **kwargs)
|
||||
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
|
@ -119,9 +119,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{{comp_form|crispy}}
|
||||
|
||||
<input type="submit" name="submit-edit-component" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% if component.get_resolved_image %}
|
||||
|
@ -0,0 +1,28 @@
|
||||
<div class="dropdown">
|
||||
<input autocomplete="off" data-ac-url="{{custom.search_url}}" data-bs-toggle="dropdown" class="form-control{% if widget.errors %} is-invalid{% endif %}" type="text" placeholder="Search...">
|
||||
|
||||
<div class="d-flex align-items-center" id="{{widget.attrs.id}}-dflex-container">
|
||||
{% if custom.current_instance %}
|
||||
{% if custom.image_field_name %}
|
||||
<div class="flex-shrink-0">
|
||||
{% if custom.image %}
|
||||
<img src="{{custom.image.url}}" style="max-width:64px;max-height:64px;" class="mr-3">
|
||||
{% else %}
|
||||
{% load static %}
|
||||
<img src="{% static 'css/icons/card-image.svg' %}" style="width:64px;max-height:64px;" class="mr-3">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div class="flex-grow-1 ms-3">
|
||||
{% if custom.current_instance %}
|
||||
{{custom.current_instance}}
|
||||
{% else %}
|
||||
<span class="text-secondary">None selected</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<ul id="{{widget.attrs.id}}-ac-ul" class="dropdown-menu">
|
||||
</ul>
|
||||
<input type="hidden" {% if widget.value != None %}value="{{widget.value}}"{%endif%} name={{widget.name}}>
|
||||
</div>
|
@ -1,7 +0,0 @@
|
||||
<div class="dropdown">
|
||||
<input autocomplete="off" data-bs-toggle="dropdown" class="form-control{% if widget.errors %} is-invalid{% endif %}" type="text" {% if widget.value != None %}value="{{widget.value}}"{%endif%}
|
||||
{% for name, value in widget.attrs.items %}{% if value is not False and name != 'id' %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %} id="{{widget.attrs.id}}_search_field">
|
||||
<ul id="{{form.manufacturer.id_for_label}}-ac-ul" class="dropdown-menu">
|
||||
</ul>
|
||||
<input type="hidden" value="" name={{widget.name}}>
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user