Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何继承和重写django模型类来创建listOfStringsField?_Python_Django_Inheritance_Django Models - Fatal编程技术网

Python 如何继承和重写django模型类来创建listOfStringsField?

Python 如何继承和重写django模型类来创建listOfStringsField?,python,django,inheritance,django-models,Python,Django,Inheritance,Django Models,我想为django模型创建一个新类型的字段,它基本上是一个listofstring。因此,在模型代码中,您将具有以下内容: 型号。py: from django.db import models class ListOfStringsField(???): ??? class myDjangoModelClass(): myName = models.CharField(max_length=64) myFriends = ListOfStringsField() #

我想为django模型创建一个新类型的字段,它基本上是一个listofstring。因此,在模型代码中,您将具有以下内容:

型号。py:

from django.db import models

class ListOfStringsField(???):
    ???

class myDjangoModelClass():
    myName = models.CharField(max_length=64)
    myFriends = ListOfStringsField() # 
myclass = myDjangoModelClass()
myclass.myName = "bob"
myclass.myFriends = ["me", "myself", "and I"]

myclass.save()

id = myclass.id

loadedmyclass = myDjangoModelClass.objects.filter(id__exact=id)

myFriendsList = loadedclass.myFriends
# myFriendsList is a list and should equal ["me", "myself", "and I"]
other.py:

from django.db import models

class ListOfStringsField(???):
    ???

class myDjangoModelClass():
    myName = models.CharField(max_length=64)
    myFriends = ListOfStringsField() # 
myclass = myDjangoModelClass()
myclass.myName = "bob"
myclass.myFriends = ["me", "myself", "and I"]

myclass.save()

id = myclass.id

loadedmyclass = myDjangoModelClass.objects.filter(id__exact=id)

myFriendsList = loadedclass.myFriends
# myFriendsList is a list and should equal ["me", "myself", "and I"]
按照以下规定,您将如何编写此字段类型

  • 我们不想创建一个字段,它只是将所有字符串填充在一起,并在一个字段中用标记将它们分隔开来,如。在某些情况下,这是一个很好的解决方案,但我们希望保持字符串数据的规范化,以便django以外的工具可以查询数据
  • 该字段应自动创建存储字符串数据所需的任何辅助表
  • 理想情况下,辅助表应该只有每个唯一字符串的一个副本。这是可选的,但最好有
在Django代码中,看起来我想做一些类似于ForeignKey所做的事情,但是文档很少

这导致了以下问题:

  • 这能做到吗
  • 是否已经完成(如果是,在哪里完成)
  • 关于Django,有没有关于如何扩展和重写它们的模型类,特别是它们的关系类的文档?我还没有看到很多关于他们代码这方面的文档,但是有

这就是它的来源。

我认为您需要的是一个。

有一些关于创建自定义字段的非常好的文档

然而,我认为你想得太多了。听起来您实际上只需要一个标准外键,但它还具有将所有元素作为单个列表检索的附加功能。因此,最简单的方法就是使用ForeignKey,并在模型上定义
get\u myfield\u as\u list
方法:

class Friends(model.Model):
    name = models.CharField(max_length=100)
    my_items = models.ForeignKey(MyModel)

class MyModel(models.Model):
    ...

    def get_my_friends_as_list(self):
        return ', '.join(self.friends_set.values_list('name', flat=True))

现在,在MyModel的实例上调用
get\u my\u friends\u as\u list()
将根据需要返回字符串列表。

我也认为您的做法是错误的。试图让Django字段创建辅助数据库表几乎肯定是错误的方法。这将是非常困难的,并且如果您试图使您的解决方案变得普遍有用,可能会使第三方开发人员感到困惑

如果您试图在单个列中存储一个非规范化的数据块,我将采用与您链接的方法类似的方法,序列化Python数据结构并将其存储在TextField中。如果希望Django以外的工具能够对数据进行操作,则可以序列化为JSON(或其他具有广泛语言支持的格式):


如果您只需要一个类似django Manager的描述符,它允许您对与模型关联的字符串列表进行操作,那么您可以手动创建一个联接表,并使用描述符来管理关系。这并不完全是你所需要的,但是。

感谢所有回答的人。即使我没有直接使用你的答案,这些例子和链接也让我朝着正确的方向前进

我不确定这是否已准备好生产,但到目前为止,它似乎在我的所有测试中都起作用

class ListValueDescriptor(object):

   def __init__(self, lvd_parent, lvd_model_name, lvd_value_type, lvd_unique, **kwargs):
      """
         This descriptor object acts like a django field, but it will accept
         a list of values, instead a single value.
         For example:
            # define our model
            class Person(models.Model):
               name = models.CharField(max_length=120)
               friends = ListValueDescriptor("Person", "Friend", "CharField", True, max_length=120)

            # Later in the code we can do this
            p = Person("John")
            p.save() # we have to have an id
            p.friends = ["Jerry", "Jimmy", "Jamail"]
            ...
            p = Person.objects.get(name="John")
            friends = p.friends
            # and now friends is a list.
         lvd_parent - The name of our parent class
         lvd_model_name - The name of our new model
         lvd_value_type - The value type of the value in our new model
                        This has to be the name of one of the valid django
                        model field types such as 'CharField', 'FloatField',
                        or a valid custom field name.
         lvd_unique - Set this to true if you want the values in the list to
                     be unique in the table they are stored in. For
                     example if you are storing a list of strings and
                     the strings are always "foo", "bar", and "baz", your
                     data table would only have those three strings listed in
                     it in the database.
         kwargs - These are passed to the value field.
      """
      self.related_set_name = lvd_model_name.lower() + "_set"
      self.model_name = lvd_model_name
      self.parent = lvd_parent
      self.unique = lvd_unique

      # only set this to true if they have not already set it.
      # this helps speed up the searchs when unique is true.
      kwargs['db_index'] = kwargs.get('db_index', True)

      filter = ["lvd_parent", "lvd_model_name", "lvd_value_type", "lvd_unique"]

      evalStr = """class %s (models.Model):\n""" % (self.model_name)
      evalStr += """    value = models.%s(""" % (lvd_value_type)
      evalStr += self._params_from_kwargs(filter, **kwargs) 
      evalStr += ")\n"
      if self.unique:
         evalStr += """    parent = models.ManyToManyField('%s')\n""" % (self.parent)
      else:
         evalStr += """    parent = models.ForeignKey('%s')\n""" % (self.parent)
      evalStr += "\n"
      evalStr += """self.innerClass = %s\n""" % (self.model_name)

      print evalStr

      exec (evalStr) # build the inner class

   def __get__(self, instance, owner):
      value_set = instance.__getattribute__(self.related_set_name)
      l = []
      for x in value_set.all():
         l.append(x.value)

      return l

   def __set__(self, instance, values):
      value_set = instance.__getattribute__(self.related_set_name)
      for x in values:
         value_set.add(self._get_or_create_value(x))

   def __delete__(self, instance):
      pass # I should probably try and do something here.


   def _get_or_create_value(self, x):
      if self.unique:
         # Try and find an existing value
         try:
            return self.innerClass.objects.get(value=x)
         except django.core.exceptions.ObjectDoesNotExist:
            pass

      v = self.innerClass(value=x)
      v.save() # we have to save to create the id.
      return v

   def _params_from_kwargs(self, filter, **kwargs):
      """Given a dictionary of arguments, build a string which 
      represents it as a parameter list, and filter out any
      keywords in filter."""
      params = ""
      for key in kwargs:
         if key not in filter:
            value = kwargs[key]
            params += "%s=%s, " % (key, value.__repr__())

      return params[:-2] # chop off the last ', '

class Person(models.Model):
   name = models.CharField(max_length=120)
   friends = ListValueDescriptor("Person", "Friend", "CharField", True, max_length=120)

最终,我认为,如果将其深入到django代码中,并更像ManyToManyField或ForeignKey那样工作,则效果会更好。

您所描述的听起来与标记非常相似。
那么,为什么不使用呢?

它的工作方式很有魅力,您可以独立于应用程序安装它,而且它的API非常容易使用。

这绝对是可能的,尽管我不知道具体细节。我说阅读他们的邮件列表并查看文档,但最终你可能不得不挖掘Django的来源。我现在正在挖掘来源。如果我真的想出了一些有效的方法,我会尝试在这里发布。我在下面发布了我的尝试,这看起来很有效。所以我在下面的尝试确实有效,但非常脆弱且容易出错(我本以为ForeignKey属于Friends类。我遗漏了什么吗?是的,我可能想得太多了,但如果我能创建我想要的字段,我认为它通常会很有用。我认为FK也是一种方法。添加方法以列表形式检索朋友+1。我刚刚有机会查看您提供的链接。)osted.我认为它比我目前所拥有的更接近于我试图实现的。感谢!+1,如果它用于非规范化,则只使用此方法!否则,进行规范化!注意get_db_prep_save现在需要4个参数(从django 1.5开始)我注意到这个类在添加之前必须保存,因为在保存之前ID不存在。我认为如果从RelatedField和Field继承,这是可以修复/纠正的,但我仍在努力理解代码。经过更多的实验,这是可行的,但非常脆弱,特别是在t方面o名称空间,它必须存在于models.py中。我将继续研究它,并希望开发一个更干净的版本。此外,如果它没有按照OP希望的方式工作,那么可以很容易地查看它是如何在那里完成的,并根据他的需要进行更改。很好!我必须进一步研究。