如何从列表中提取JSON值并以django模型形式呈现它?
我正在尝试使用下面的模型呈现Django模型表单。问题是其中一个模型字段是JSONField。这是一个长度为1的列表,其中包含一些JSON数据。当我呈现模型表单时,如何从列表中提取JSON值并以django模型形式呈现它?,django,django-forms,django-templates,Django,Django Forms,Django Templates,我正在尝试使用下面的模型呈现Django模型表单。问题是其中一个模型字段是JSONField。这是一个长度为1的列表,其中包含一些JSON数据。当我呈现模型表单时,number字段呈现列表,没有任何问题。但是我想从列表中的JSON中提取phone值并呈现它。我已经尝试在模板中提取它,但它没有按预期工作 如何从JSON中提取phone值并将其呈现在表单中?例如,当我使用视图呈现id 1的数据时,我应该在名称字段中看到'Client_1',在数字字段中看到'1234567890' 我使用Django
number
字段呈现列表,没有任何问题。但是我想从列表中的JSON中提取phone
值并呈现它。我已经尝试在模板中提取它,但它没有按预期工作
如何从JSON中提取phone
值并将其呈现在表单中?例如,当我使用视图呈现id 1的数据时,我应该在名称字段中看到'Client_1',在数字字段中看到'1234567890'
我使用Django 3.1和Django Crispy表单来渲染模型表单
数据如数据库中的客户端表所示:
id name number
1 Client_1 [{'type': 'mobile', 'phone': '1234567890'}]
2 Client_2 [{'type': 'mobile', 'phone': '3334445555'}]
3 Client_3 [{'type': 'mobile', 'phone': '9876543210'}]
models.py:
forms.py:
clients.html模板:
{% load crispy_forms_tags %}
<form method="POST">
<div class="form-row">
<div class="form-group col-md-6">
{{ form.name | as_crispy_field }}
</div>
<div class="form-group col-md-6">
{% for item in form.number %}
{{ item.0.phone | as_crispy_field }}
{% endfor %}
</div>
</div>
</form>
您需要将字段动态添加到表单中,以下是一个工作示例:
类ClientForm(forms.ModelForm):
def uuu init uuuu(self,*args,instance=None,**kwargs):
super(ClientForm,self)。\uuuuu init\uuuu(*args,instance=instance,**kwargs)
例如:
对于索引,枚举中的obj(instance.number):
self.fields[f'phone_{index}']=forms.CharField(initial=obj.get('phone','')
def save(self,commit=True):
对于索引,枚举中的obj(self.instance.number):
obj['phone']=self.cleaned_data.get(f'phone_{index}','')
返回super(ClientForm,self).save(commit=commit)
类元:
模型=客户端
字段=['name']
然后,您的模板应为:
{%load crispy_forms_tags%}
{{form.name | as_crispy_field}
{{form.phone|as|u crispy_field}
NB:如果您总是将手机存储在列表中,则应将默认设置为您的JsonField:
类客户端(models.Model):
name=models.TextField()
编号=models.JSONField(默认值=列表)
我在表单中尝试了上面的init和save方法。但它仍然显示如我的问题所示的列表。我不确定我是否做错了什么。我编辑了我的答案,你需要更新你的模板。对不起,我忙于工作。我将很快更新我的答案。我只是好奇。{{form.phone_1|as_crispy_field}}
对任何ID都有效吗?或者表单.phone_1
必须是动态的吗?我可以确认您的方法有效。我只需要在模板中做一个小小的更改,就是根据我收到的回溯错误将{form.phone_1 | as_crispy_field}
更改为{form.phone_0 | as_crispy_field}
。在做了这个小的更新之后,它工作得非常好。非常感谢您调查此事。老实说,我不知道init方法在做什么…:-)我实际上发现了一个数字字段为空的场景。这导致了一个错误。为了克服这个问题,我稍微修改了ini函数:`if instance.number:for index,obj in enumerate(instance.number):self.fields[f'phone}']=forms.CharField(initial=obj.get('phone',''),else:self.fields[f'phone']=forms.CharField(initial='')`
from .models import Client
class ClientForm(forms.ModelForm):
class Meta:
model = Client
fields = '__all__'
{% load crispy_forms_tags %}
<form method="POST">
<div class="form-row">
<div class="form-group col-md-6">
{{ form.name | as_crispy_field }}
</div>
<div class="form-group col-md-6">
{% for item in form.number %}
{{ item.0.phone | as_crispy_field }}
{% endfor %}
</div>
</div>
</form>
def clients(request, pk):
instance = Client.objects.get(pk=pk)
if request.method == 'POST':
form = ClientForm(request.POST, instance=instance)
if form.is_valid():
form.save()
else:
form = ClientForm(instance=instance)
return render(request, 'clients.html', {'form': form})