【问题标题】:Django: How to make an unique, blank models.CharField?Django:如何制作一个独特的空白models.CharField?
【发布时间】:2011-06-17 20:19:42
【问题描述】:

假设我有一个描述办公室打印机的模型。他们可能准备好工作或不准备工作(可能在存储区或已购买但尚未在办公室......)。该模型必须有一个表示打印机实际位置的字段(“秘书办公室”、“接待处”……)。不能有两个重复的位置,如果它不工作,它就不应该有一个位置。

我想要一个列表,其中显示所有打印机,并且每个打印机都有它所在的位置(如果有的话)。像这样的:

ID | Location
1  | "Secretary's office"
2  |
3  | "Reception"
4  | 

有了这个,我可以知道有两台打印机正在工作(1 和 3),其他打印机离线(2 和 4)。

模型的第一种方法,应该是这样的:

class Printer(models.Model):
      brand = models.CharField( ...
      ...
      location = models.CharField( max_length=100, unique=True, blank=True )

但这不能正常工作。您只能使用一个空白位置存储一个寄存器。它在数据库中存储为空字符串,并且不允许您插入多次(数据库表示该字段还有另一个空字符串)。如果将“null=True”参数添加到此参数,它的行为方式相同。这是因为,默认值是空字符串,而不是在相应列中插入 NULL 值。

在网上搜索我找到了http://www.maniacmartin.com/2010/12/21/unique-nullable-charfields-django/,它试图以不同的方式解决问题。他说最干净的可能是最后一个,他在其中继承了 CharField 类并重写了一些方法以在数据库中存储不同的值。代码如下:

from django.db import models
class NullableCharField(models.CharField):
     description = "CharField that obeys null=True"
     def to_python(self, value):
         if isinstance(value, models.CharField):
             return value
         return value or ""

     def get_db_prep_value(self, value):
         return value or None

这很好用。您可以存储多个没有位置的寄存器,因为它不是插入一个空字符串,而是存储一个 NULL。这样做的问题是它使用 Nones 而不是空字符串显示空白位置。

ID | Location
1  | "Secretary's office"
2  | None
3  | "Reception"
4  | None

我认为有一个方法(或多个)必须指定如何在模型和数据库类管理器之间以两种方式(数据库到模型和模型到数据库)转换数据。

这是拥有独特的空白 CharField 的最佳方式吗?

谢谢,

【问题讨论】:

    标签: django-models unique


    【解决方案1】:

    尝试检查此线程。

    Unique fields that allow nulls in Django

    【讨论】:

    • 讨论了如何在数据库中存储 NULL 而不是空字符串。他们设计了一些解决方案,例如覆盖模型的保存方法或子类化 CharField 类。这部分在我的情况下已解决,但我想将 NULL 数据转换为空字符串而不是 None。
    【解决方案2】:

    您可以使用模型方法以自定义方式输出值。

    像这样(在你的模型类中):

    def location_output(self):
        "Returns location and replaces None values with an empty string"
        if self.location:
            return self.location
        else:
            return ""
    

    然后你可以在这样的视图中使用它。

    >>> Printer.objects.create(location="Location 1")
    <Printer: Printer object>
    >>> Printer.objects.create(location=None)
    <Printer: Printer object>
    >>> Printer.objects.get(id=1).location_output()
    u'Location 1'
    >>> Printer.objects.get(id=2).location_output()
    ''
    

    在你的模板中,像这样。

    {{ printer.location_output }}
    

    【讨论】:

      猜你喜欢
      • 2020-02-19
      • 1970-01-01
      • 2013-11-16
      • 2017-01-29
      • 1970-01-01
      • 2019-11-27
      • 2020-11-27
      • 1970-01-01
      • 2013-05-19
      相关资源
      最近更新 更多