Как фильтровать опции с другим значением select в админ-формах django
У меня есть модели Address, city, state с отношением один к одному, и я пытаюсь фильтровать города по штату, когда хочу добавить новый адрес, поэтому проблема в том, что я могу видеть все города для любого штата, и я понятия не имею, как это исправить. Есть идеи?
модели
class State(models.Model):
state_name = models.CharField(max_length=50)
def __str__(self) -> str:
return self.state_name
class City(models.Model):
cityـname = models.CharField(max_length=50)
state = models.ForeignKey(to=State,on_delete=models.CASCADE)
def __str__(self) -> str:
return self.cityـname
class Adrress(models.Model):
user = models.ForeignKey(to=User,on_delete=models.CASCADE)
city = models.ForeignKey(to=City,on_delete=models.CASCADE)
description = models.TextField()
def __str__(self) -> str:
return self.description
admin
@admin.register(State)
class StateAdmin(admin.ModelAdmin):
pass
@admin.register(City)
class CityAdmin(admin.ModelAdmin):
pass
@admin.register(Adrress)
class AdrressAdmin(admin.ModelAdmin):
pass
поэтому я ожидаю, что когда я хочу добавить новый адрес, я увижу форму, подобную этой и при смене штата в выпадающем списке городов, чтобы был виден только город для этого штата
Как я пробовал
использование пользовательской формы
поэтому я изменил код вот так в админке и сделал пользовательский виджет и Jquery
admin
@admin.register(Adrress)
class AdrressAdmin(admin.ModelAdmin):
form = AdrressAdminForm
Формы
class RelatedChoieField(forms.widgets.Select):
def __init__(self, attrs=None, choices=()):
super().__init__(attrs,choices)
self.data = {}
for obj in City.objects.all():
if not obj.state in self.data.keys():
self.data[obj.state.state_name] = [obj.cityـname]
else:
self.data[obj.state.state_name].append(obj.cityـname)
def render(self, name, value, attrs=None, renderer=None):
html = super().render(name, value, attrs)
inline_code = mark_safe(
f"<script>obj ={dumps(self.data,indent=4)};$(\"#id_state\").change(()=>{{$(\"#id_city\").innerHTML=\"\";for(var i=0;i<obj[$(\"#id_state\").find(\":selected\").text()].length;i++){{$(\"#id_city\").innerHTML+=$(\"<option></option>\").innerHTML=obj[$(\"#id_state\").find(\":selected\").text()][i]}} }})</script>"
)
return html + inline_code
class AdrressAdminForm(forms.ModelForm):
state = forms.ModelChoiceField(
queryset=State.objects.all(),
widget=RelatedChoieField,
)
class Meta:
model= Adrress
fields = ["user","state","city","description"]
Но все еще не происходит фильтрации, так что же мне делать? Любая идея будет оценена по достоинству!
Может быть, это сработает.
class AdrressAdminForm(forms.ModelForm):
state = forms.ModelChoiceField(
queryset=State.objects.all(),
widget=RelatedChoieField,
)
class Meta:
model= Adrress
fields = ["user","state","city","description"]
def __init(self, city=None, *args, **kwargs):
super().__init__()
if city: self.fields['state'].queryset = State.objects.filter(city=city)