【问题标题】:django Charfield suitable for a primary key?django Charfield 适合主键吗?
【发布时间】:2016-06-30 07:52:55
【问题描述】:

在我的 django 模型中,我想将下面的字段 unique_id 设置为主键,因为这将是模型查询中使用的字段。它满足unique=Truenull=False。但是,由于 django 在后台将 AutoField 设置为主键,我不确定 CharField(使用唯一的 3 个字符代码)是否适合作为主键,或者这是否是次优的?

class PaymentMethod(models.Model):
    unique_id = models.CharField(max_length=3)
    last_updated = models.DateTimeField(auto_now=True)

【问题讨论】:

    标签: django-models


    【解决方案1】:

    CharField设置为主键没有错,通过将模型更改为:

    class PaymentMethod(models.Model):
        unique_id = models.CharField(max_length=3, primary_key=True)
        last_updated = models.DateTimeField(auto_now=True)
    

    事实上,如果 unique_id 是您将要查询的字段,那么使用它是非常有意义的。您的其他选择是使用现有模型,但使用 unique=True

    class PaymentMethod(models.Model):
        unique_id = models.CharField(max_length=3, unique=True)
        last_updated = models.DateTimeField(auto_now=True)
    

    在这种情况下,您的主键将是一个自动递增的整数,如您之前所述。

    另一个选项取决于您希望在PaymentMethod 模型中存储的记录数量;以及应用程序中其他地方使用数据的位置。太考虑使用model choices field。模型选择字段可能在您的付款或订单模型上(取决于您的应用程序和您要执行的操作)。这消除了对外键的需求,并可能减少应用中的查询数量。

    它可能看起来像这样:

    class Payment(models.Model):
        VISA = 'VIS'
        CREDIT = 'CRE'
        MASTER_CARD = 'MAS'
        PAYPAL = 'PAL'
        PAYMENT_OPTIONS= (
            (VISA, 'Visa'),
            (CREDIT, 'Credit Card'),
            (MASTER_CARD, 'Master Card'),
            (PAYPAL, 'Paypal')
        )
    
        items = models.ForeignKey(Item)
        date = models.DateField(auto_now=True)
        ...
        payment_method = models.CharField(max_length=3, choices=PAYMENT_OPTIONS, default=VISA)
    

    PAYMENT_OPTIONS 可用于在使用 django model forms 时在表单上呈现下拉框。否则,用户选择仅限于此模型中列出的选项。 如果您只有PaymentMethod(s) 的一小部分,此方法会更有效。

    【讨论】:

    • 谢谢,我注意到您没有在选项选项中指定 primary_key=True。使用选择是否会使这变得多余?我对该字段只有 5 个选择,所以这可能是一个不错的选择,但是使用选择会自动创建索引还是以另一种方式更有效。我也刚刚看到设置unique=True 会自动创建一个索引,所以前两个选项(主键或仅使用唯一)之间有很大区别吗?
    • 如果您执行选择路由,那么您将在模型中创建一个列,您通常会在其中拥有指向PaymentMethod 的外键。基本上任何你会做payment_type=models.ForeignKey(PaymentMethod) 的地方你都会做`payment_choice=models.CharField(....,choices=)。基本上完全不需要 PaymentMethod 模型。
    • 太棒了,非常感谢。我有另一个类似的模型,只有 3 个选择,但是可以有多个选项。是否可以将其引入模型,还是必须是单独的 M2M 模型?
    【解决方案2】:

    可以使用CharField 作为主键。您只需将该字段标记为主键。

    field_name = models.CharField(primary_key=True, max_length=100)
    

    但我不推荐它,因为:

    • 在 url 中使用主键(通常在 Rest API 中) - 但并非所有字符都可以在 url 中使用
    • DRF (django-rest-framework) 使用默认不捕获某些字符的 url 模式(例如“.”)
    • 主键必须是唯一的 - 如果字段是字符串,则更难实现,尤其是当您让用户定义它时

    【讨论】:

    • CharFields 必须定义一个 'max_length' 属性。
    • 虽然语法正确,但我建议不要使用 varchar(100) 主键。根据我的阅读,在 10-20 范围之外,事情开始变得低效。
    猜你喜欢
    • 1970-01-01
    • 2020-12-26
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    • 2020-02-05
    相关资源
    最近更新 更多