簡體   English   中英

Python Django:是否可以轉換列中的逗號分隔值並將每個值檢索為查詢集行

[英]Python Django: Is it possible to convert comma separated values in a column and retrieve each value as query set rows

我在表中的數據集是這樣的,讓我們將表名稱為plans_tracker(第一個屏幕截圖)我正在嘗試檢索查詢集,如(第二個屏幕截圖)。 有人可以幫我解決這個問題嗎,我無法修改表結構。 我正在嘗試在 Django 模板中執行此操作一行包含“Plan A”和“1,2,3”列...

...應該變成三行“Plan A”和“1”,“Plan A”和“2”,以及“Plan A”和“3”。

使用 PostgreSQL 時是可能的。 我不確定如何使用其他數據庫后端來實現它。 請注意,您存儲數據的方式並不理想,可以使用更好的解決方案。 下面有 2 個更好的解決方案示例,其中之一是獨立於數據庫的。

假設您有一個 model 定義如下(我已將示例中的不相關字段替換為單個字符字段):

from django.core.validators import validate_comma_separated_integer_list
from django.db import models

class Plan(models.Model):
    group = models.CharField(max_length=256)
    student_course_records = models.TextField(validators=[validate_comma_separated_integer_list])

鑒於此,您可以通過 Django 的Func使用 string_to_array 將學生列表轉換為string_to_array數組:

Plan.objects.annotate(
    students=Func(
        F('student_course_records'), 
        Value(','), 
        function='string_to_array',
        output_field=ArrayField(models.IntegerField())
     )
)

這將為您的 object 添加一個名為students的“虛擬”字段。 它將代表一個數組中的所有學生 ID,以后更容易處理。

由於您現在有一個 ID 數組,您可以使用unnest function 將這些值分解為單獨的記錄:

Plan.objects.annotate(student=Func(Func(F('student_course_records'), Value(','), function='string_to_array', output_field=ArrayField(models.IntegerField())), function='unnest') )

現在,您將擁有單獨的記錄,而不是students字段,每個記錄都有一個student值。 請注意, student_course_records在每條記錄中仍然可用,但您可以使用valuesvalues_listonlyexclude來更改它。

為了簡化編寫這些查詢,您可以繼承Func

class StringToArray(models.Func):
    function = 'string_to_array'

    def __init__(self, *args, output_field, **kwargs):
        super().__init__(*args, output_field=ArrayField(output_field), **kwargs)


class Unnest(models.Func):
    function = 'unnest'
    arity = 1

然后您的電話將如下所示:

Plan.objects.annotate(
    student=Unnest(
        StringToArray(
            F('student_course_records'), 
            Value(','), 
            output_field=models.IntegerField(),
        )
    )
)

正如我之前所說,這個數據 model 並不理想,因為它需要在每次數據訪問時解析逗號分隔的列表。 更不用說在這個字段上查詢數據的麻煩了。 有 2 種更好的方法:使用ArrayField代替逗號分隔的文本字段或使用嵌套的 model。 第一個仍然需要 PostgreSQL 數據庫,第二種方法可以與 Django 官方支持的任何數據庫一起使用,但在這種簡單的用例中可能看起來很嘈雜和冗余。 對於第一種方法,您可以將 model 定義為:

class Plan(models.Model):
    group = models.CharField(max_length=256)
    student_course_records = ArrayField(models.IntegerField())

對於此 model,您的查詢將簡化為:

Plan.objects.annotate(
    student=Unnest(F('student_course_records'))
)

在所有情況下, student_course_records都將表示為一個數組,無需將其轉換為其他任何內容。

第二種方法看起來像:

class Plan(models.Model):
    group = models.CharField(max_length=256)

class Student(models.Model):
    plan = models.ForeignKey(Plan, related_name='student_course_records', on_delete=models.CASCADE

對於此 model,您的查詢將簡化為:

Student.objects.all()

使用可選的select_relatedvalues調用同時從Plan model 中提取數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM