What is the most efficient way to store a list in the Django models?

后端 未结 12 726
执笔经年
执笔经年 2020-11-28 01:27

Currently I have a lot of python objects in my code similar to the following:

class MyClass():
  def __init__(self, name, friends):
      self.myName = name
         


        
相关标签:
12条回答
  • 2020-11-28 01:50

    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

    0 讨论(0)
  • 2020-11-28 01:57

    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."      
    
    0 讨论(0)
  • 2020-11-28 01:58
    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')
    
    0 讨论(0)
  • 2020-11-28 02:03

    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

    0 讨论(0)
  • 2020-11-28 02:04

    "Premature optimization is the root of all evil."

    With that firmly in mind, let's do this! Once your apps hit a certain point, denormalizing data is very common. Done correctly, it can save numerous expensive database lookups at the cost of a little more housekeeping.

    To return a list of friend names we'll need to create a custom Django Field class that will return a list when accessed.

    David Cramer posted a guide to creating a SeperatedValueField on his blog. Here is the code:

    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()
    
    0 讨论(0)
  • 2020-11-28 02:04

    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.

    0 讨论(0)
提交回复
热议问题