Django中如何跨多表搜索slug并将商品添加到OrderItem的一对多外键字段
解决方案
方案1:保留现有表结构,扩展slug匹配逻辑
适合产品类型固定、不想改动现有模型结构的场景,只需调整视图层的匹配逻辑即可:
修改views.py中的post方法,拿到slug后依次遍历所有产品表查询,匹配成功后赋值给对应外键字段即可:
def post(self, request, *args, **kwargs): slug = request.data.get('slug') variations = request.data.get('variations', []) if slug is None: return Response({"message": "Invalid request"}, status=HTTP_400_BAD_REQUEST) item_instance = None target_field = None # 优先查询gamingpc表 try: item_instance = gamingpc.objects.get(slug=slug) target_field = "item" except gamingpc.DoesNotExist: # 匹配失败再查询PcComponent表 try: item_instance = PcComponent.objects.get(slug=slug) target_field = "product" except PcComponent.DoesNotExist: return Response({"message": "对应商品不存在"}, status=HTTP_404_NOT_FOUND) # 创建OrderItem时动态赋值对应外键 order_item = OrderItem.objects.create( user=request.user, ordered=False, **{target_field: item_instance} ) # 后续处理规格、加购等其他业务逻辑
注意需要保证所有产品表的slug全局唯一,避免出现同slug匹配错误的问题。
方案2:使用Django通用外键重构模型
适合后续会新增多个产品类型的场景,无需每次新增产品都修改OrderItem字段:
首先修改models.py,引入Django自带的通用外键能力:
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType class OrderItem(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) ordered = models.BooleanField(default=False) # 通用外键核心字段 content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, blank=True, null=True) object_id = models.PositiveIntegerField(blank=True, null=True) # 对外统一使用item字段关联任意产品表 item = GenericForeignKey('content_type', 'object_id')
再修改views.py中的匹配逻辑:
def post(self, request, *args, **kwargs): slug = request.data.get('slug') variations = request.data.get('variations', []) if slug is None: return Response({"message": "Invalid request"}, status=HTTP_400_BAD_REQUEST) # 所有产品模型列表,后续新增产品只需往这里加模型即可 product_models = [gamingpc, PcComponent] item_instance = None for model in product_models: try: item_instance = model.objects.get(slug=slug) break except model.DoesNotExist: continue if not item_instance: return Response({"message": "对应商品不存在"}, status=HTTP_404_NOT_FOUND) # 直接给item字段赋值任意产品实例即可,无需区分字段 order_item = OrderItem.objects.create( user=request.user, ordered=False, item=item_instance ) # 后续其他业务逻辑
内容的提问来源于stack exchange,提问作者Ritwik Shaw
相关产品推荐
相关产品推荐

