Django 모델에 목록을 저장하는 가장 효율적인 방법은 무엇입니까?
현재 내 코드에는 다음과 유사한 많은 파이썬 객체가 있습니다.
class MyClass():
def __init__(self, name, friends):
self.myName = name
self.myFriends = [str(x) for x in friends]
이제 이것을 장고 모델로 바꾸고 싶습니다. 여기서 self.myName은 문자열 필드이고 self.myFriends는 문자열 목록입니다.
from django.db import models
class myDjangoModelClass():
myName = models.CharField(max_length=64)
myFriends = ??? # what goes here?
목록은 파이썬에서 일반적인 데이터 구조이기 때문에 장고 모델 필드가있을 것으로 예상됩니다. 나는 ManyToMany 또는 OneToMany 관계를 사용할 수 있다는 것을 알고 있지만 코드에서 추가 간접적 인 것을 피하고 싶었습니다.
편집하다:
사람들이 유용하다고 생각하는 관련 질문을 추가했습니다 .
이 관계가 Friends
테이블 에 대한 일대 다 외래 키 관계로 더 잘 표현되지 않습니까? 나는 myFriends
단지 문자열 이라는 것을 이해 하지만 더 나은 디자인은 Friend
모델 을 만들고 MyClass
결과 테이블에 대한 외래 키 구현 을 포함하는 것이라고 생각 합니다.
"조기 최적화는 모든 악의 근원입니다."
이를 확실하게 염두에두고이 작업을 수행하십시오! 앱이 특정 지점에 도달하면 데이터의 비정규 화가 매우 일반적입니다. 올바르게 수행하면 약간의 하우스 키핑 비용으로 많은 고가의 데이터베이스 조회를 절약 할 수 있습니다.
list
친구 이름 을 반환하려면 액세스 할 때 목록을 반환하는 사용자 지정 Django Field 클래스를 만들어야합니다.
David Cramer는 자신의 블로그에 SeperatedValueField 작성에 대한 안내서를 게시했습니다. 코드는 다음과 같습니다.
from django.db import models
class SeparatedValuesField(models.TextField):
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
self.token = kwargs.pop('token', ',')
super(SeparatedValuesField, self).__init__(*args, **kwargs)
def to_python(self, value):
if not value: return
if isinstance(value, list):
return value
return value.split(self.token)
def get_db_prep_value(self, value):
if not value: return
assert(isinstance(value, list) or isinstance(value, tuple))
return self.token.join([unicode(s) for s in value])
def value_to_string(self, obj):
value = self._get_val_from_obj(obj)
return self.get_db_prep_value(value)
The logic of this code deals with serializing and deserializing values from the database to Python and vice versa. Now you can easily import and use our custom field in the model class:
from django.db import models
from custom.fields import SeparatedValuesField
class Person(models.Model):
name = models.CharField(max_length=64)
friends = SeparatedValuesField()
A simple way to store a list in Django is to just convert it into a JSON string, and then save that as Text in the model. You can then retrieve the list by converting the (JSON) string back into a python list. Here's how:
The "list" would be stored in your Django model like so:
class MyModel(models.Model):
myList = models.TextField(null=True) # JSON-serialized (text) version of your list
In your view/controller code:
Storing the list in the database:
import simplejson as json # this would be just 'import json' in Python 2.7 and later
...
...
myModel = MyModel()
listIWantToStore = [1,2,3,4,5,'hello']
myModel.myList = json.dumps(listIWantToStore)
myModel.save()
Retrieving the list from the database:
jsonDec = json.decoder.JSONDecoder()
myPythonList = jsonDec.decode(myModel.myList)
Conceptually, here's what's going on:
>>> myList = [1,2,3,4,5,'hello']
>>> import simplejson as json
>>> myJsonList = json.dumps(myList)
>>> myJsonList
'[1, 2, 3, 4, 5, "hello"]'
>>> myJsonList.__class__
<type 'str'>
>>> jsonDec = json.decoder.JSONDecoder()
>>> myPythonList = jsonDec.decode(myJsonList)
>>> myPythonList
[1, 2, 3, 4, 5, u'hello']
>>> myPythonList.__class__
<type 'list'>
If you are using Django >= 1.9 with Postgres you can make use of ArrayField advantages
A field for storing lists of data. Most field types can be used, you simply pass another field instance as the base_field. You may also specify a size. ArrayField can be nested to store multi-dimensional arrays.
It is also possible to nest array fields:
from django.contrib.postgres.fields import ArrayField
from django.db import models
class ChessBoard(models.Model):
board = ArrayField(
ArrayField(
models.CharField(max_length=10, blank=True),
size=8,
),
size=8,
)
As @thane-brimhall mentioned it is also possible to query elements directly. Documentation reference
As this is an old question, and Django techniques must have changed significantly since, this answer reflects Django version 1.4, and is most likely applicable for v 1.5.
Django by default uses relational databases; you should make use of 'em. Map friendships to database relations (foreign key constraints) with the use of ManyToManyField. Doing so allows you to use RelatedManagers for friendlists, which use smart querysets. You can use all available methods such as filter
or values_list
.
Using ManyToManyField
relations and properties:
class MyDjangoClass(models.Model):
name = models.CharField(...)
friends = models.ManyToManyField("self")
@property
def friendlist(self):
# Watch for large querysets: it loads everything in memory
return list(self.friends.all())
You can access a user's friend list this way:
joseph = MyDjangoClass.objects.get(name="Joseph")
friends_of_joseph = joseph.friendlist
Note however that these relations are symmetrical: if Joseph is a friend of Bob, then Bob is a friend of Joseph.
class Course(models.Model):
name = models.CharField(max_length=256)
students = models.ManyToManyField(Student)
class Student(models.Model):
first_name = models.CharField(max_length=256)
student_number = models.CharField(max_length=128)
# other fields, etc...
friends = models.ManyToManyField('self')
Remember that this eventually has to end up in a relational database. So using relations really is the common way to solve this problem. If you absolutely insist on storing a list in the object itself, you could make it for example comma-separated, and store it in a string, and then provide accessor functions that split the string into a list. With that, you will be limited to a maximum number of strings, and you will lose efficient queries.
In case you're using postgres, you can use something like this:
class ChessBoard(models.Model):
board = ArrayField(
ArrayField(
models.CharField(max_length=10, blank=True),
size=8,
),
size=8,
)
if you need more details you can read in the link below: https://docs.djangoproject.com/pt-br/1.9/ref/contrib/postgres/fields/
You can store virtually any object using a Django Pickle Field, ala this snippet:
http://www.djangosnippets.org/snippets/513/
Storing a list of strings in Django model:
class Bar(models.Model):
foo = models.TextField(blank=True)
def set_list(self, element):
if self.foo:
self.foo = self.foo + "," + element
else:
self.foo = element
def get_list(self):
if self.foo:
return self.foo.split(",")
else:
None
and you can call it like this:
bars = Bar()
bars.set_list("str1")
bars.set_list("str2")
list = bars.get_list()
if list is not None:
for bar in list:
print bar
else:
print "List is empty."
Using one-to-many relation (FK from Friend to parent class) will make your app more scalable (as you can trivially extend the Friend object with additional attributes beyond the simple name). And thus this is the best way
My solution, may be it helps someone:
import json
from django.db import models
class ExampleModel(models.Model):
_list = models.TextField(default='[]')
@property
def list(self):
return json.loads(self._list)
@list.setter
def list(self, value):
self._list = json.dumps(self.list + value)
'IT story' 카테고리의 다른 글
다른 디렉토리에 소스 파일이있는 Makefile (0) | 2020.07.14 |
---|---|
C에서 변수 선언 배치 (0) | 2020.07.14 |
iPad / iPhone 호버 문제로 인해 사용자가 링크를 두 번 클릭 (0) | 2020.07.14 |
Amazon S3와 Amazon EC2 인스턴스의 차이점은 무엇입니까? (0) | 2020.07.13 |
일식에서 "디버그 관점으로 자동 전환"모드를 끄려면 어떻게해야합니까? (0) | 2020.07.13 |