使用Django+React开发时,如何显示关联表名称而非ID?
解决Django+React关联表显示ID而非名称的问题
方案1:快速实现只显示名称(适合仅需名称的场景)
步骤1:修改Django Serializer
将Serializer中的PrimaryKeyRelatedField替换为SerializerMethodField,直接返回关联表的名称字段:
class ProductoSerializer(serializers.ModelSerializer): # 自定义每个关联字段的返回值 categoria = serializers.SerializerMethodField() marca = serializers.SerializerMethodField() modelo = serializers.SerializerMethodField() calidad = serializers.SerializerMethodField() proveedor = serializers.SerializerMethodField() # 分别实现每个字段的取值方法 def get_categoria(self, obj): return obj.categoria.nombre def get_marca(self, obj): return obj.marca.nombre def get_modelo(self, obj): return obj.modelo.nombre def get_calidad(self, obj): return obj.calidad.nombre def get_proveedor(self, obj): return obj.proveedor.nombre class Meta: model = Producto fields = [ 'id', 'nombre', 'precio', 'stock', 'categoria', 'marca', 'modelo', 'calidad', 'proveedor' ]
这个方法的优势:
- 无需修改React代码,
ProductoCard.jsx中{producto.categoria}直接显示名称 - 创建/更新时依然可以传ID,Serializer会自动处理模型外键关联
补充:如果关联模型的__str__已返回名称
如果你的Categoria、Marca等模型已经定义了__str__方法返回nombre(比如def __str__(self): return self.nombre),可以更简单地用StringRelatedField替换:
class ProductoSerializer(serializers.ModelSerializer): categoria = serializers.StringRelatedField() marca = serializers.StringRelatedField() modelo = serializers.StringRelatedField() calidad = serializers.StringRelatedField() proveedor = serializers.StringRelatedField() class Meta: model = Producto fields = [ 'id', 'nombre', 'precio', 'stock', 'categoria', 'marca', 'modelo', 'calidad', 'proveedor' ]
注意:StringRelatedField是只读字段,创建/更新时依然需要传ID,Serializer会自动映射到外键字段。
方案2:返回完整关联对象(适合需要更多关联字段的场景)
如果后续需要用到关联表的其他字段(比如Categoria的描述),可以用嵌套序列化:
步骤1:创建关联模型的Serializer
# 新增CategoriaSerializer class CategoriaSerializer(serializers.ModelSerializer): class Meta: model = Categoria fields = ['id', 'nombre'] # 同理创建其他关联模型的Serializer class MarcaSerializer(serializers.ModelSerializer): class Meta: model = Marca fields = ['id', 'nombre'] class ModeloSerializer(serializers.ModelSerializer): class Meta: model = Modelo fields = ['id', 'nombre'] class CalidadSerializer(serializers.ModelSerializer): class Meta: model = Calidad fields = ['id', 'nombre'] class ProveedorSerializer(serializers.ModelSerializer): class Meta: model = Proveedor fields = ['id', 'nombre']
步骤2:修改ProductoSerializer
使用嵌套序列化返回完整对象,同时添加write_only的ID字段用于创建/更新:
class ProductoSerializer(serializers.ModelSerializer): # 只读的嵌套字段,返回完整关联对象 categoria = CategoriaSerializer(read_only=True) marca = MarcaSerializer(read_only=True) modelo = ModeloSerializer(read_only=True) calidad = CalidadSerializer(read_only=True) proveedor = ProveedorSerializer(read_only=True) # 只用于写入的ID字段,映射到对应的外键 categoria_id = serializers.PrimaryKeyRelatedField(queryset=Categoria.objects.all(), source='categoria', write_only=True) marca_id = serializers.PrimaryKeyRelatedField(queryset=Marca.objects.all(), source='marca', write_only=True) modelo_id = serializers.PrimaryKeyRelatedField(queryset=Modelo.objects.all(), source='modelo', write_only=True) calidad_id = serializers.PrimaryKeyRelatedField(queryset=Calidad.objects.all(), source='calidad', write_only=True) proveedor_id = serializers.PrimaryKeyRelatedField(queryset=Proveedor.objects.all(), source='proveedor', write_only=True) class Meta: model = Producto fields = [ 'id', 'nombre', 'precio', 'stock', 'categoria', 'marca', 'modelo', 'calidad', 'proveedor', 'categoria_id', 'marca_id', 'modelo_id', 'calidad_id', 'proveedor_id' ]
步骤3:修改React代码
1. 更新ProductoFormPage.jsx的状态和表单字段
将状态中的关联字段改为xxx_id,对应Serializer的写入字段:
const [productos, setProductos] = useState({ nombre: "", precio: "", stock: "", categoria_id: "", marca_id: "", modelo_id: "", calidad_id: "", proveedor_id: "", });
然后修改每个select的value和onChange:
// 示例:Categoria下拉框 <select value={productos.categoria_id} onChange={(e) => setProductos({ ...productos, categoria_id: e.target.value })} > <option value="">---------Categoría---------</option> {categorias.map(categoria => ( <option key={categoria.id} value={categoria.id}> {categoria.nombre} </option> ))} </select>
其他下拉框(Marca、Modelo等)同理修改为marca_id、modelo_id等。
2. 更新ProductoCard.jsx显示名称
现在返回的是完整对象,需要访问nombre属性:
<h3>Categoria: {producto.categoria.nombre}</h3> <h3>Marca: {producto.marca.nombre}</h3> <h3>Modelo: {producto.modelo.nombre}</h3> <h3>Calidad: {producto.calidad.nombre}</h3> <h3>Proveedor: {producto.proveedor.nombre}</h3>
内容的提问来源于stack exchange,提问作者Andres Vilca
相关产品推荐
相关产品推荐

