如何通过HTML表单创建Person实例并保存至AuraDB?
问题描述
多数在线教程都是讲解如何用Django将模型实例保存到本地数据库,我尝试实现将数据存入Neo4j(AuraDB连接正常),但运行项目后访问http://127.0.0.1:8000/person出现异常。我希望通过用户表单输入创建Person实例并保存到AuraDB,当前实现存在问题,相关代码如下:
Person模型(models/person.py)
from neomodel import StructuredNode, StringProperty, IntegerProperty,UniqueIdProperty, RelationshipTo from myapi.models.city import City class Person(StructuredNode): uid = UniqueIdProperty() name = StringProperty(unique_index=False) age = IntegerProperty(index=True, default=0) email = StringProperty(unique_index=True) # Relations : city = RelationshipTo(City, 'LIVES_IN') friends = RelationshipTo('Person','FRIEND') def __unicode__(self): return self.uid
表单定义(views/forms.py)
from django import forms from splitjson.widgets import SplitJSONWidget from myapi.models import Person class testForm(forms.Form): attrs = {'class': 'special', 'size': '40'} data = forms.CharField(widget=SplitJSONWidget(attrs=attrs, debug=True)) class Meta: model = Person
URL配置(urls.py)
from django.urls import re_path as url from myapi.views import * from django.urls import path urlpatterns = [ path('', home, name='home'), path('home', home, name='home'), path('sign-up', sign_up, name='sign_up'), path('test-dict', test_dict, name='test_dict'), path('person',personDetails), path('getAllPersons',getAllPersons), path('city',cityDetails), path('getAllCities',getAllCities), path('connectPaC',connectPaC), path('connectPaP',connectPaP) ]
视图函数(home.py中的test_dict)
from django.template import RequestContext from .forms import testForm from django.template.loader import render_to_string def test_dict(request): json = {'name': 1, 'age': 4} form = testForm(request.POST or None, initial={'data': json}) if form.is_valid(): # validate and save pass template = 'myapi/test_template.html' #context = RequestContext(request, render_to_string(form)) return render(request, template, {'form': form})
Person相关视图(views/persons.py)
from django.http import JsonResponse from myapi.models import Person from django.views.decorators.csrf import csrf_exempt import json from django.shortcuts import render, redirect def getAllPersons(request): if request.method == 'GET': try: persons = Person.nodes.all() response = [] for person in persons : obj = { "uid": person.uid, "name": person.name, "age": person.age, } response.append(obj) return JsonResponse(response, safe=False) except: response = {"error": "Error occurred"} return JsonResponse(response, safe=False) @csrf_exempt def personDetails(request): if request.method == 'GET': # get one person by name name = request.GET.get('name', ' ') try: person = Person.nodes.get(name=name) response = { "uid": person.uid, "name": person.name, "age": person.age, } return JsonResponse(response, safe=False) except : response = {"error":"Error occurred"} return JsonResponse(response, safe=False) #return render(response, 'myapi/test_template.html') if request.method == 'POST': # create one person json_data = json.loads(request.body) name = json_data['first_name'] email = str(json_data['email']) try: person = Person(name=name, email=email) person.save() response = { "uid": person.uid, } return JsonResponse(response) except : response = {"error":"Error occurred"} return JsonResponse(response, safe=False) if request.method == 'PUT': # update one person json_data = json.loads(request.body) name = json_data['name'] age = int(json_data['age']) uid = json_data['uid'] try: person = Person.nodes.get(uid=uid) person.name = name person.age = age person.save() response = { "uid": person.uid, "name": person.name, "age": person.age, } return JsonResponse(response, safe=False) except: response = {"error":"Error occurred"} return JsonResponse(response, safe=False) if request.method == 'DELETE': # delete one person json_data = json.loads(request.body) uid = json_data['uid'] try: person = Person.nodes.get(uid=uid) person.delete() response = {"success": "Person deleted"} return JsonResponse(response, safe=False) except: response = {"error":"Error occurred"} return JsonResponse(response, safe=False)
修复步骤
1. 修正表单定义
当前用的forms.Form是普通表单,无法直接关联Person模型,改用forms.ModelForm直接映射模型字段,无需复杂的JSON组件:
from django import forms from myapi.models import Person class PersonForm(forms.ModelForm): class Meta: model = Person fields = ['name', 'age', 'email'] # 直接指定需要用户输入的字段
2. 调整test_dict视图,处理表单提交逻辑
原视图未实现保存逻辑,修改后直接从表单提取数据创建Person实例并保存:
from django.shortcuts import render from .forms import PersonForm from myapi.models import Person def test_dict(request): form = PersonForm(request.POST or None) if request.method == 'POST' and form.is_valid(): # 从表单获取清洗后的数据 person_data = form.cleaned_data # 创建Person实例并保存到AuraDB person = Person(**person_data) person.save() template = 'myapi/test_template.html' return render(request, template, {'form': form})
3. 修复personDetails视图的POST逻辑
原POST方法处理的是JSON请求,表单提交是application/x-www-form-urlencoded格式,需改用request.POST.get()获取数据,同时修正字段名(模型中是name而非first_name):
@csrf_exempt def personDetails(request): # ... 保留其他请求方法逻辑 ... if request.method == 'POST': # 处理表单提交或普通POST请求 name = request.POST.get('name') email = request.POST.get('email') age = request.POST.get('age', 0) # 设置默认值避免空值报错 try: person = Person(name=name, email=email, age=int(age)) person.save() response = {"uid": person.uid} return JsonResponse(response) except Exception as e: # 打印错误用于调试,上线后可移除 print(str(e)) response = {"error": str(e)} return JsonResponse(response, safe=False) # ... 保留其他请求方法逻辑 ...
4. 调整模板渲染(test_template.html)
确保模板正确渲染表单,添加CSRF令牌:
<form method="POST" action="{% url 'test_dict' %}"> {% csrf_token %} {{ form.as_p }} <button type="submit">提交</button> </form>
5. 调试建议
- 提交表单后查看控制台输出,可快速定位具体错误
- 确认
settings.py中Neo4j的连接配置正确 - 原
/person的GET请求需要传name参数(如/person?name=xxx),可修改逻辑支持不传参数时返回所有数据(与getAllPersons合并)
内容的提问来源于stack exchange,提问作者Ranjan
相关产品推荐
相关产品推荐

