【发布时间】:2020-01-19 19:35:02
【问题描述】:
使用 Postgres 特定的 ArrayField,我试图对 ArrayFields 的长度求和。
查询在 shell 中可以正常工作,但在本地开发服务器上却不行。我已将错误缩小到第 19 行的最后一个注释:“annotate(total=Sum("length"))”,因为没有最后一个 .annotate(...).values(...)部分。
我还运行了“makemigrations”和“migrate”以便更新数据库。
错误:
psycopg2.errors.InvalidCursorName:游标“_django_curs_19180_1”不存在
光标“_django_curs_19180_1”不存在
调试输出:
('SELECT "product_design_assembledfromcomponent"."id", '
'"product_design_assembledfromcomponent"."assembled_id_id", '
'"product_design_assembledfromcomponent"."quantity", '
'"product_design_assembledfromcomponent"."designed_with_id_id", '
'"product_design_assembledfromcomponent"."position", '
'"product_design_assembledfromcomponent"."description", '
'"product_design_assembledfromcomponent"."assembled_inhouse", (SELECT '
'SUM(ARRAY_LENGTH(U0."position")) AS "total" FROM "product_design_multistep" '
'U0 WHERE U0."assembly_id" = ("product_design_assembledfromcomponent"."id") '
'GROUP BY U0."assembly_id" LIMIT 1) AS "taken" FROM '
'"product_design_assembledfromcomponent" WHERE '
'"product_design_assembledfromcomponent"."assembled_id_id" = %s')
The above exception (function array_length(character varying[]) does not exist LINE 1: ...edfromcomponent"."assembled_inhouse", (SELECT SUM(ARRAY_LENG... ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. ) was the direct cause of the following exception:
代码:
1 from django.db.models import Q, Sum, Count, Subquery, OuterRef
2 from django_postgres_extensions.models.functions import ArrayLength
3
4 class ProductionStepForm(forms.ModelForm):
5 helper = FormHelper()
6 helper.layout = Layout(
7 Div("assemblies", "description",
8 css_class="col-md-7",
9 ),
10 )
11
12 helper.add_input(Submit('submit', 'Submit', css_class='btn-primary'))
13
14
15 def __init__(self, *args, **kwargs):
16 design = kwargs.pop("design")
17 super(ProductionStepForm, self).__init__(*args, **kwargs)
18
19 taken = MultiStep.objects.filter(assembly=OuterRef("id")).annotate(length=ArrayLength("position")).values("assembly").annotate(total=Sum("length")).values("total")
20 assembly_query = AssembledFromComponent.objects.filter(assembled_id=design).annotate(taken=Subquery(taken[:1]))
21 self.fields["assemblies"] = forms.ModelMultipleChoiceField(queryset=assembly_query, required=False)
22 self.Meta.fields.append("assemblies")
23
24
25 class Meta:
26 model = ProductionStep
27 fields = [
28 "description"
29 ]
提前感谢您的帮助!
编辑:添加模型
1 class MultiStep(models.Model):
2 step = models.ForeignKey(ProductionStep, on_delete=models.PROTECT, null=True, blank=True)
3 assembly = models.ForeignKey(AssembledFromComponent, on_delete=models.PROTECT, null=True, blank=True)
4 quantity = models.DecimalField(decimal_places=6, max_digits=12, default=1)
5 position = ArrayField(
models.CharField(max_length=10, blank=True),
size=40,
blank=True,
null=True,
help_text="A subset of the set of positions defined for an assembly"
)
6 class AssembledFromComponent(models.Model):
7 # ID of the new component
8 assembled_id = models.ForeignKey(
9 DesignedComponent,
10 on_delete=models.PROTECT,
11 related_name='assembled_id'
12 )
13 quantity = models.DecimalField(decimal_places=6, max_digits=12)
14 # ID of a component used to make a new component
15 designed_with_id = models.ForeignKey(
16 DesignedComponent,
17 on_delete=models.PROTECT,
18 related_name='designed_with_id'
19 )
20 position = models.CharField(
21 max_length=200,
22 blank=True,
23 null=True,
24 help_text="Enter a single position or a comma separated list of positions with length = quantity"
25 )
26 description = models.TextField(
27 max_length=1000,
28 help_text='Enter a brief description of the assembly',
29 null=True,
30 blank=True,
31 )
32 assembled_inhouse = models.BooleanField(default=False)
Edit2:我将改为使 MultiStep.position 字段原子而不是使用 ArrayField,这使事情变得不那么复杂。
我仍然认为原始问题很奇怪,因为在我看来,数组长度似乎不可求和。
【问题讨论】:
-
什么是位置字段,如果您想了解更多关于您的模型的信息,也会很有帮助
标签: django postgresql psycopg2