You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Axios将Django外键模型实例传递至React

问题:从User实例中关联获取完整地址层级数据

我有一个Address模型,通过外键关联多个地址细分模型;还有一个User模型,通过外键关联单个Address实例。现在需要从User对象中获取完整的地址层级数据(比如User->Address->type->type_code、User->Address->province->province_name这类嵌套结构),并将包含地址信息的用户数据传给React前端存储使用。


一、Models.py 代码

class AddressType(models.Model):
    add_type_name = models.CharField(_("Address Type"), max_length=30)
    add_type_code = models.CharField(_("Address Type Code "), max_length=2)

    def __str__(self):
        return self.add_type_name


class AddressProvince(models.Model):
    add_prov_name = models.CharField(_("Province Name"), max_length=20)
    
    def __str__(self):
        return self.add_prov_name

class AddressBranch(models.Model):
    add_branch_name = models.CharField(_("Branch Name"), max_length=100)
    add_branch_code = models.CharField(_("Branch Code"), max_length=10)

    def __str__(self):
        return self.add_branch_name
    

class AddressDepartment(models.Model):
    add_dept_name = models.CharField(_("Department Name"), max_length=150)
    add_dept_code = models.CharField(_("Department Code "), max_length=5)
    add_dept_floor = models.PositiveIntegerField(_("Department Floor"), default=0)
    
    def __str__(self):
        return self.add_dept_name
    
class AddressContact(models.Model):
    add_cont_name = models.CharField(_("Contact Name"), max_length=200)
    add_cont_position = models.CharField(_("Contact Position"), max_length=200)

    def __str__(self):
        return self.add_cont_name

class AddressSection(models.Model):
    add_sec_name = models.CharField(_("Section Name"), max_length=250)

    class Meta:
        verbose_name_plural = "Address Section"
    def __str__(self):
        return self.add_sec_name
    

class Address(models.Model):
    add_type = models.ForeignKey(AddressType, on_delete=models.CASCADE, blank=True, null=True, related_name="address_type")
    add_prov = models.ForeignKey(AddressProvince, on_delete=models.CASCADE, blank=True, null=True,related_name="address_province")
    add_branch = models.ForeignKey(AddressBranch, on_delete=models.CASCADE, blank=True, null=True,related_name="address_branch")
    add_dept = models.ForeignKey(AddressDepartment, on_delete=models.CASCADE,blank=True, null=True, related_name="address_department")
    add_contact = models.ForeignKey(AddressContact, on_delete=models.CASCADE,blank=True, null=True, related_name="address_contact")
    add_section = models.ForeignKey(AddressSection, on_delete=models.CASCADE,blank=True, null=True, related_name="address_section")
    add_is_sys = models.BooleanField(_("Is System User?"), default=False)

    def __str__(self):
        return self.add_section.add_sec_name

class UserGroup(models.Model):
    user_group_name = models.CharField(_("Group"), max_length=100)
    user_group_code = models.CharField(_("Group Code"), max_length=2)

    def __str__(self):
        return self.user_group_code


class User(models.Model):
    user_name = models.CharField(_("Name"), max_length=180)
    user_password = models.CharField(_("Password"), max_length=100)
    user_email = models.CharField(_("Email"), max_length=150)
    user_AZB = models.CharField(_("AZB"), max_length=20)
    user_group = models.ForeignKey(UserGroup, on_delete=models.CASCADE, related_name="user_group")
    user_position = models.CharField(_("Position"), max_length=100)
    user_address = models.ForeignKey(Address, on_delete=models.CASCADE, related_name="user_address")

二、Views.py 中的登录接口代码

@csrf_exempt
def userLogin(request):
    email = request.POST.get('user_email')
    password = request.POST.get('user_password')
    user  = models.User.objects.get(user_email = email , user_password = password)
    userData = ser.serialize('json', [user])
    userAddress = fetch_address(user.user_address.id)
    if user: 
        return JsonResponse(
            userData, userAddress, safe=False)
    else:
        return JsonResponse({'bool': False})

三、React Login.jsx 提交代码

const submitForm = (e)=>{
    e.preventDefault()
    const userFormData = new FormData;
    userFormData.append('user_email', userData.user_email)
    userFormData.append('user_password', userData.user_password)
    
      axios.post(baseURL+'/login/', userFormData).
      then((res)=>{
        // sessionStorage.setItem('userLoggedIn', true)
        // sessionStorage.setItem('userData', JSON.stringify(res.data.user[0]))
      }).catch((err)=>{
        console.log(err.response.data)
      })
  }

四、尝试编写的地址获取函数(报错)

编写了fetch_address函数尝试获取完整地址信息,但运行时报错:TypeError: 'str' object is not callable

def fetch_address(add_id):
    
    findAddress = models.Address.objects.get(pk=add_id)
    data = []
    if findAddress:
        data.append({"add_id": add_id})
    if findAddress.add_type:
        addType = models.AddressType.objects.get(pk=findAddress.add_type.id)
        data.append ({
            "add_type_name" : addType.add_type_name,
            "add_type_code" : addType.add_type_code,
            "add_type_id" : findAddress.add_type.id,
        })
    if findAddress.add_prov:
         addProv = models.AddressProvince.objects.get(pk=findAddress.add_prov.id)
         data.append({
            "add_prov_name" : addProv.add_prov_name,
            "add_prov_id" : findAddress.add_prov.id,
        })
    if findAddress.add_branch:
        addBranch = models.AddressBranch.objects.get(pk=findAddress.add_branch.id)
        data.append({
            "add_branch_code" : addBranch.add_branch_code,
            "add_branch_name" : addBranch.add_branch_name,
            "add_branch_id" : findAddress.add_prov.id,
        })
    if findAddress.add_dept:
        addDept = models.AddressDepartment.objects.get(pk=findAddress.add_dept.id)
        data.append({
            "add_dept_code": addDept.add_dept_code,
            "add_dept_name": addDept.add_dept_name,
            "add_dept_floor": addDept.add_dept_floor,
            "add_dept_id": findAddress.add_dept.id
        })
    if findAddress.add_contact:
        addContact = models.AddressContact.objects.get(pk=findAddress.add_contact.id)
        data.append({
            "add_cont_code": addContact.add_cont_name,
            "add_cont_pos": addContact.add_cont_position,
            "add_cont_id": findAddress.add_contact.id
        })
    if findAddress.add_section:
        addSection = models.AddressSection.objects.get(pk=findAddress.add_section.id)
        data.append({
            "add_sec_name": addSection.add_sec_name,
            "add_sec_id": findAddress.add_contact.id
        })
    if data:
        return json.dumps(data) 
    else:
        return {}

问题修正方案

1. 修复fetch_address函数的错误

原函数存在返回值类型混乱、字段引用错误、重复查询关联对象等问题,修正后:

def fetch_address(add_id):
    find_address = models.Address.objects.get(pk=add_id)
    address_data = {
        "add_id": add_id,
        "add_type": {},
        "add_prov": {},
        "add_branch": {},
        "add_dept": {},
        "add_contact": {},
        "add_section": {}
    }

    if find_address.add_type:
        address_data["add_type"] = {
            "add_type_name": find_address.add_type.add_type_name,
            "add_type_code": find_address.add_type.add_type_code,
            "add_type_id": find_address.add_type.id
        }
    if find_address.add_prov:
        address_data["add_prov"] = {
            "add_prov_name": find_address.add_prov.add_prov_name,
            "add_prov_id": find_address.add_prov.id
        }
    if find_address.add_branch:
        address_data["add_branch"] = {
            "add_branch_code": find_address.add_branch.add_branch_code,
            "add_branch_name": find_address.add_branch.add_branch_name,
            "add_branch_id": find_address.add_branch.id
        }
    if find_address.add_dept:
        address_data["add_dept"] = {
            "add_dept_code": find_address.add_dept.add_dept_code,
            "add_dept_name": find_address.add_dept.add_dept_name,
            "add_dept_floor": find_address.add_dept.add_dept_floor,
            "add_dept_id": find_address.add_dept.id
        }
    if find_address.add_contact:
        address_data["add_contact"] = {
            "add_cont_name": find_address.add_contact.add_cont_name,
            "add_cont_position": find_address.add_contact.add_cont_position,
            "add_cont_id": find_address.add_contact.id
        }
    if find_address.add_section:
        address_data["add_section"] = {
            "add_sec_name": find_address.add_section.add_sec_name,
            "add_sec_id": find_address.add_section.id
        }
    
    # 移除空字段,只保留有数据的内容
    return {k: v for k, v in address_data.items() if v}

2. 修复Views.py中的登录接口

原接口JsonResponse传参错误,且未正确合并用户与地址数据,修正后:

import json
from django.core import serializers

@csrf_exempt
def userLogin(request):
    email = request.POST.get('user_email')
    password = request.POST.get('user_password')
    try:
        # 预加载所有关联模型,避免N+1查询
        user = models.User.objects.select_related(
            'user_address',
            'user_address__add_type',
            'user_address__add_prov',
            'user_address__add_branch',
            'user_address__add_dept',
            'user_address__add_contact',
            'user_address__add_section'
        ).get(user_email=email, user_password=password)
        
        # 序列化用户数据并转为字典
        user_data = json.loads(serializers.serialize('json', [user]))[0]['fields']
        user_data['id'] = user.id
        # 合并地址数据
        user_data['user_address'] = fetch_address(user.user_address.id)
        
        return JsonResponse(user_data, safe=False)
    except models.User.DoesNotExist:
        return JsonResponse({'bool': False})

3. 前端React代码调整

现在后端返回包含完整地址层级的用户对象,前端可直接存储并访问:

const submitForm = (e)=>{
    e.preventDefault()
    const userFormData = new FormData;
    userFormData.append('user_email', userData.user_email)
    userFormData.append('user_password', userData.user_password)
    
    axios.post(baseURL+'/login/', userFormData)
      .then((res)=>{
        sessionStorage.setItem('userLoggedIn', true)
        sessionStorage.setItem('userData', JSON.stringify(res.data))
        // 示例:访问地址层级数据
        const storedUser = JSON.parse(sessionStorage.getItem('userData'))
        console.log(storedUser.user_address.add_type.add_type_code)
        console.log(storedUser.user_address.add_prov.add_prov_name)
      }).catch((err)=>{
        console.log(err.response.data)
      })
  }

内容的提问来源于stack exchange,提问作者Mr.Trent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:39:52