Dio*_*ias 5 django django-models django-orm django-views django-rest-framework
我们现在面临这样的情况,我想获得更有经验的用户\xe2\x80\x99s的意见。我们现在是 Django 4、Python 3.9。
\n目前的情况:
\n我们的系统已经在生产中运行了一段合理的时间,我们需要根据用户的选择在后端更改一些返回到我们的前端应用程序(Web、mobile\xe2\x80\xa6)的数据。
\n重要的是:目前无法选择前端方面的更改。
\n我们需要根据另一个表上现有或不对应的数据覆盖一个模型中的某些属性。
\n表格(Django 模型):
\nAgentSearch(该数据每天都会被 ETL 过程替换)
\n代理(代理可以定义的可选数据)
\n对于我们现在的要求,所有查询集都将从 开始进行AgentSearch。这个想法是获取Agent数据,而不是AgentSearch每次有代理链接到数据时就获取数据。
今天我们得到这样的结果:
\nAgentSearch.objects.all()
我知道像这样注释新列会更容易:
\n # using a different attribute name\n NEW_member_first_name=Case(\n When(\n agent__id__isnull=True,\n then=F("member_first_name"),\n ),\n default=F("agent__first_name"),\n ),\nRun Code Online (Sandbox Code Playgroud)\n这将需要我们对前端进行更改。
\n如果我们尝试:
\n # using the same attribute name\n member_first_name=Case(\n When(\n agent__id__isnull=True,\n then=F("member_first_name"),\n ),\n default=F("agent__first_name"),\n ),\nRun Code Online (Sandbox Code Playgroud)\nDjango 会抛出:
\n`ValueError Exception saying: The annotation 'member_first_name' conflicts with a field on the model.`\nRun Code Online (Sandbox Code Playgroud)\n我们已经尝试从基本查询中删除“可覆盖”属性。例子:
\n # Tell Django ORM to not get the column from DB\n AgentSearch.objects.all().defer('member_first_name')\n .annotate(\n member_first_name=Case(\n When(\n agent__id__isnull=True,\n then=F("member_first_name"),\n ),\n default=F("agent__first_name"),\n ),\nRun Code Online (Sandbox Code Playgroud)\n仍然:
\n`ValueError Exception saying: The annotation 'member_first_name' conflicts with a field on the model.`\nRun Code Online (Sandbox Code Playgroud)\n还尝试仅强制基本查询中的不可“覆盖”属性的值。例子:
\n # Tell Django ORM to not get the column from DB\n AgentSearch.objects.all().values('some_other_attrbs')\n .annotate(\n member_first_name=Case(\n When(\n agent__id__isnull=True,\n then=F("member_first_name"),\n ),\n default=F("agent__first_name"),\n ),\nRun Code Online (Sandbox Code Playgroud)\n仍然:
\n`ValueError Exception saying: The annotation 'member_first_name' conflicts with a field on the model.`\nRun Code Online (Sandbox Code Playgroud)\n我还尝试创建一个 django 上下文管理器来执行此操作,但它会抛出相同的错误。
\n在您看来,什么是一种优雅的方式来做到这一点?我们找到了解决方案,但看起来很丑陋。
\n目前如何运作:
\nclass BaseAgentSearch(AbstractBaseModel):\n ...\n class Meta:\n abstract = True\n\nclass AgentSearch(BaseAgentSearch):\n class Meta:\n db_table = "app_agentsearch"\n # setting to false, since this model will act only as a "reader"\n managed = False\n ###########################################################\n # Original DB columns are mapped to a temp_ attribute name\n ###########################################################\n temp_member_first_name = models.CharField(\n max_length=64, db_column="member_first_name"\n )\n temp_member_last_name = models.CharField(\n max_length=64, db_column="member_last_name"\n )\n temp_member_email = models.EmailField(\n max_length=64, blank=True, db_column="member_email"\n )\n\n\nclass AgentSearchWrite(BaseAgentSearch):\n class Meta:\n db_table = "app_agentsearch"\n\n member_first_name = models.CharField(max_length=64)\n member_last_name = models.CharField(max_length=64)\n member_email = models.EmailField(max_length=64, blank=True)\nRun Code Online (Sandbox Code Playgroud)\n然后查询为:
\n AgentSearch.objects.all()\n .annotate(\n member_first_name=Case(\n When(\n agent__id__isnull=True,\n then=F("temp_member_first_name"),\n ),\n default=F("agent__first_name"),\n ),\n member_last_name=Case(\n When(agent__id__isnull=True, then=F("temp_member_last_name")),\n default=F("agent__last_name"),\n ),\n member_email=Case(\n When(agent__id__isnull=True, then=F("temp_member_email")),\n default=F("agent__email"),\n ),\nRun Code Online (Sandbox Code Playgroud)\n这按预期工作。但看起来真的很奇怪而且丑陋。而且,为了添加/更新数据,我们现在应该使用AgentSearchWrite在数据库和模型上具有正确列的模型。
| 归档时间: |
|
| 查看次数: |
878 次 |
| 最近记录: |