development

Django : 모델의 목록 필드?

big-blog 2020. 12. 10. 20:50
반응형

Django : 모델의 목록 필드?


내 모델에는 세 개의 목록이있는 필드가 필요합니다. 예 : [[1, 3, 4], [4, 2, 6], [8, 12, 3], [3, 3, 9]]. 이 데이터를 데이터베이스에 저장할 수있는 필드가 있습니까?


JSON을 사용하여 문자열로 변환하고 문자열로 저장할 수 있습니다.

예를 들면

In [3]: json.dumps([[1, 3, 4], [4, 2, 6], [8, 12, 3], [3, 3, 9]])

Out[3]: '[[1, 3, 4], [4, 2, 6], [8, 12, 3], [3, 3, 9]]'

클래스에 메서드를 추가하여 자동으로 변환 할 수 있습니다.

import json


class Foobar(models.Model):
    foo = models.CharField(max_length=200)

    def set_foo(self, x):
        self.foo = json.dumps(x)

    def get_foo(self):
        return json.loads(self.foo)

Django 1.9 및 postgresql을 사용하는 경우 JSONField라는 새 클래스가 있으므로 대신 사용해야합니다. 여기에 링크가 있습니다.

youtube 에서 PostgreSQL JSON 및 배열에 대한 좋은 이야기가 있습니다. 보세요, 아주 좋은 정보가 있습니다.


PostgreSQL을 사용하는 경우 중첩 된 ArrayField와 함께 ArrayField를 사용할 수 있습니다. https://docs.djangoproject.com/en/2.2/ref/contrib/postgres/fields/

이렇게하면 데이터 구조가 기본 데이터베이스에 알려집니다. 또한 ORM은 특별한 기능을 제공합니다.

하지만 직접 GIN 인덱스를 만들어야합니다 (위 링크 참조, 아래 링크 참조 : https://docs.djangoproject.com/en/2.2/ref/contrib/postgres/fields/#indexing-arrayfield ). .

(편집 : 최신 Django LTS에 대한 업데이트 된 링크,이 기능은 적어도 1.8 이후 존재합니다.)


1.10과 같은 더 최신 버전의 Django를 사용하고 있고 DB가 Postgres 인 경우 Django 프레임 워크에 기본으로 제공되는 django-taggit 또는 다른 대안보다 더 나은 새로운 ArrayField 가 있습니다.

from django.db import models
from django.contrib.postgres.fields import ArrayField

class ChessBoard(models.Model):
    board = ArrayField(
        ArrayField(
            models.CharField(max_length=10, blank=True),
            size=8,
        ),
        size=8,
    )

나는 그것이 당신을 도울 것이라고 생각합니다.

django.db 가져 오기 모델에서
수입 ast

class ListField (models.TextField) :
    __metaclass__ = models.SubfieldBase
    description = "파이썬 목록 저장"

    def __init __ (self, * args, ** kwargs) :
        super (ListField, self) .__ init __ (* args, ** kwargs)

    def to_python (self, value) :
        값이 아닌 경우 :
            값 = []

        인스턴스 (값, 목록) 인 경우 :
            반환 값

        ast.literal_eval (값) 반환

    def get_prep_value (self, value) :
        값이 없음 인 경우 :
            반환 값

        유니 코드 (값) 반환

    def value_to_string (self, obj) :
        값 = self._get_val_from_obj (obj)
        return self.get_db_prep_value (value)

클래스 ListModel (models.Model) :
    test_list = ListField ()

예 :

>>> ListModel.objects.create (test_list = [[1,2,3], [2,3,4,4]])

>>> ListModel.objects.get (id = 1)

>>> o = ListModel.objects.get (id = 1)
>>> o.id
1L
>>> o.test_list
[[1, 2, 3], [2, 3, 4, 4]]
>>> 

이러한 타사 패키지가 제공하는 JSON 필드를 사용하면됩니다.

이 경우 필드 값 직렬화에 대해 신경 쓸 필요가 없습니다. 내부에서 발생합니다.

도움이되기를 바랍니다.


꽤 오래된 주제이지만 "django 목록 필드"를 검색 할 때 반환되므로 Python 3 및 Django 2에서 작동하도록 수정 한 사용자 지정 django 목록 필드 코드를 공유하겠습니다. 이제 관리 인터페이스를 지원하고 eval을 사용하지 않습니다. (이것은 Prashant Gaur의 코드에서 엄청난 보안 침해입니다).

from django.db import models
from typing import Iterable

class ListField(models.TextField):
    """
    A custom Django field to represent lists as comma separated strings
    """

    def __init__(self, *args, **kwargs):
        self.token = kwargs.pop('token', ',')
        super().__init__(*args, **kwargs)

    def deconstruct(self):
        name, path, args, kwargs = super().deconstruct()
        kwargs['token'] = self.token
        return name, path, args, kwargs

    def to_python(self, value):

        class SubList(list):
            def __init__(self, token, *args):
                self.token = token
                super().__init__(*args)

            def __str__(self):
                return self.token.join(self)

        if isinstance(value, list):
            return value
        if value is None:
            return SubList(self.token)
        return SubList(self.token, value.split(self.token))

    def from_db_value(self, value, expression, connection):
        return self.to_python(value)

    def get_prep_value(self, value):
        if not value:
            return
        assert(isinstance(value, Iterable))
        return self.token.join(value)

    def value_to_string(self, obj):
        value = self.value_from_object(obj)
        return self.get_prep_value(value)

목록을 평면화 한 다음 값을 CommaSeparatedIntegerField에 저장할 수 있습니다 . 데이터베이스에서 다시 읽을 때 값을 3으로 다시 그룹화하십시오.

면책 조항 : 데이터베이스 정규화 이론에 따르면 컬렉션을 단일 필드에 저장하지 않는 것이 좋습니다. 대신 해당 세 개의 값을 자체 필드에 저장하고 외래 키를 통해 연결하는 것이 좋습니다. 하지만 현실 세계에서는 때로는 너무 번거 롭거나 느립니다.


현재 평판으로는 댓글을 달 수 없습니다. 따라서 Prashant Gaur의 답장 으로 샘플 코드에 대한 댓글을 참조하는 답변을 선택했습니다 (고마워요, Gaur-도움이되었습니다!). 그의 샘플은 python2 용입니다.

유니 코드
방법.

기능에 대한 아래 대체

get_prep_value (자기, 값) :
python3으로 실행되는 Django에서 작동해야합니다 (이 코드는 곧 사용할 예정이지만 아직 테스트되지는 않았습니다). 그래도 내가 지나가고 있다는 점에 유의하십시오.
encoding = 'utf-8', errors = 'ignore'
매개 변수
풀다()
unicode () 메서드
. 인코딩은 Django settings.py 구성과 일치해야합니다.
errors = '무시'
선택 사항입니다 (드물게 django가 잘못 구성된 예외 대신 자동 데이터 손실이 발생할 수 있음).

수입 시스템

...

    def get_prep_value (self, value) :
        값이 없음 인 경우 :
            반환 값
        sys.version_info [0]> = 3 :
            isinstance (out_data, type (b '')) 인 경우 :
                return value.decode (encoding = 'utf-8', errors = 'ignore')
        그밖에:
            isinstance (out_data, type (b '')) 인 경우 :
                unicode (value, encoding = 'utf-8', errors = 'ignore') 반환
        반환 str (값)
...



If you are using Google App Engine or MongoDB as your backend, and you are using the djangoappengine library, there is a built in ListField that does exactly what you want. Further, it's easy to query the Listfield to find all objects that contain an element in the list.

참고URL : https://stackoverflow.com/questions/22340258/django-list-field-in-model

반응형