Django курсор psycopg2 не существует - PullRequest
0 голосов
/ 19 января 2020

Используя Postgres Speci c ArrayField, я пытаюсь суммировать длины ArrayFields.

Запросы отлично работают в оболочке, но не на локальном сервере разработки. Я сузил ошибку до последней аннотации в строке 19: «annotate (total = Sum (« length »))», видя, как она работает без этого последнего .annotate (...). Values ​​(...) part.

Я также запустил «makemigrations» и «migrate», чтобы база данных была обновлена.

Ошибка:

psycopg2.errors.InvalidCursorName: cursor " _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)

Редактировать2: Вместо этого я сделаю поле MultiStep.position Atomi c, а не ArrayField, это делает вещи менее сложными.

Я все еще думаю, что оригинальная проблема любопытна, поскольку мне кажется, что длины массива не суммируемы.

1 Ответ

0 голосов
/ 20 января 2020

Судя по ошибке, ваш аргумент позиции имеет тип не массив, а символ.

(function array_length(**character varying[]**) does not exist 

array_length функция принимает в качестве аргумента только тип массива

...