Django中基于JSON数据源创建模型的最佳实践及优化咨询
Django商品数据导入与模型优化指南
一、现有模型优化建议
先给你的模型提几个实用的优化点,让结构更合理、维护更轻松:
- Product模型:
item作为主键没问题,但建议添加unique=True约束(虽然主键本身就是唯一的,但显式声明更清晰);另外可以给name加db_index=True,方便后续按名称快速查询。 - Market模型:没必要手动定义
id = models.IntegerField(primary_key=True, auto_created=True),Django默认会自动生成一个AutoField类型的主键id,删掉这行代码更简洁。 - Suburb模型:建议给
name和market设置unique_together约束,避免同一个市场下出现重复的郊区名称:class Suburb(models.Model): name = models.CharField(max_length=30) market = models.ForeignKey(Market, on_delete=models.SET_NULL, null=True) class Meta: unique_together = ('name', 'market') - ProductForSale模型:
sale主键可以换成Django默认的AutoField,手动维护Integer主键容易出现冲突;另外给product、market字段添加db_index=True,能大幅提升关联查询的速度。
二、数据导入逻辑修正
你的现有代码有两个核心问题:没有处理suburb到Market的关联,以及Product.objects.get()可能抛出DoesNotExist异常(如果数据源里的商品ID在本地不存在)。下面是修正后的实现,还加入了批量导入优化(专门应对5万+条数据的场景):
修正后的导入代码
import json import urllib.request from .models import Product, Market, Suburb, ProductForSale def import_market_products(): # 提前加载所有郊区和市场的映射,避免循环内重复查询数据库 suburb_market_map = {sub.name.lower(): sub.market for sub in Suburb.objects.select_related('market').all()} # 准备批量创建的列表,减少数据库IO product_sales_to_create = [] # 遍历每个市场(假设每个市场对应专属的JSON URL) for market in Market.objects.all(): url = f"your_json_url_for_market_{market.id}" # 替换成实际的市场对应URL response = urllib.request.urlopen(url) data = json.loads(response.read()) for entry in data['market_products']: # 处理Product:如果不存在则自动创建,避免DoesNotExist异常 product, _ = Product.objects.get_or_create( item=entry['item'], defaults={'name': entry.get('name', '')} # 假设JSON里可能带name字段,无则留空 ) # 处理Suburb与Market的关联:先匹配郊区,再获取对应市场 suburb_name = entry['suburb'].lower() market_obj = suburb_market_map.get(suburb_name) if not market_obj: # 可根据业务需求选择跳过或自动创建郊区(这里示例为跳过) print(f"Suburb {entry['suburb']} not found, skipping entry {entry['id']}") continue # 构建ProductForSale对象暂存,不立即保存 product_sale = ProductForSale( product=product, cost=entry['cost'], owner=entry['owner'], quantity=entry['quantity'], market=market_obj ) product_sales_to_create.append(product_sale) # 批量创建数据,相比循环create效率提升数倍 if product_sales_to_create: ProductForSale.objects.bulk_create(product_sales_to_create, batch_size=1000)
关键优化点说明
- 用
get_or_create替代get:确保数据源里的新商品ID能自动创建对应的Product记录,避免因商品不存在导致的报错。 - 提前加载郊区-市场映射:避免在循环内反复查询数据库,大幅减少IO开销。
- 批量创建
bulk_create:把多条SQL语句合并成一个执行,处理大量数据时速度提升非常明显;设置batch_size可以避免一次性加载过多数据到内存。 - 异常处理郊区不存在的情况:根据业务需求灵活选择跳过或自动创建郊区(如果要自动创建,需要先确认该郊区所属的市场)。
三、是否需要为每个市场单独创建模型?
完全不需要!统一用ProductForSale模型就足够了:
- 所有市场的在售商品结构都是一致的(商品、价格、卖家、数量、关联市场),拆分模型会导致大量重复代码,维护成本极高。
- 通过
ProductForSale的market外键,完全可以区分不同市场的商品,查询时只需要添加filter(market=xxx)即可。 - 未来如果某个市场有特殊字段需求,可以考虑用模型继承或OneToOneField关联扩展模型,而不是直接拆分主模型。
内容的提问来源于stack exchange,提问作者ms18
相关产品推荐
相关产品推荐

