【问题标题】:How to make an auto-filled and auto-incrementing field in django admin如何在 django admin 中创建一个自动填充和自动递增的字段
【发布时间】:2011-03-08 14:49:27
【问题描述】:

[更新:将问题标题更改为更具体]

对不起,如果我没有很好地提出问题,我不知道该怎么做:

class WhatEver():
    number = model.IntegerField('Just a Field', default=callablefunction)
...

callablefunction 在哪里进行此查询:

from myproject.app.models import WhatEver

def callablefunction():
    no = WhatEver.objects.count()
    return no + 1

想自动写下一个数字,不知道怎么做。

我收到来自callablefunction 的错误,指出它无法导入模型,我认为必须有更简单的方法来做到这一点。甚至没有必要使用它,但我不知道如何使用 pk 号。

我已经用谷歌搜索过这个问题,我唯一发现的是使用 save() 方法自动增加数字...但我想在保存之前在 <textfield> 中显示它...

你会怎么做?

【问题讨论】:

    标签: python django django-models django-admin default-value


    【解决方案1】:

    知道了!我希望这将帮助每个在 django 中制作自动填充和自动递增字段时遇到任何问题的人。解决办法是:

    class Cliente(models.Model):
        """This is the client data model, it holds all client information. This
           docstring has to be improved."""
        def number():
            no = Cliente.objects.count()
            if no == None:
                return 1
            else:
                return no + 1
    
        clientcode = models.IntegerField(_('Code'), max_length=6, unique=True, \
        default=number)
    
        [... here goes the rest of your model ...]
    

    保重:

    • number 函数不接受任何参数(甚至不接受自身)
    • 它写在之前模型中的所有内容
    • 这是在 django 1.2.1 上测试的

    此功能将自动用下一个数字填充clientcode字段(即如果您有132个客户,当您添加下一个时,该字段将填充clientcode数字133)

    我知道这在大多数实际情况下是荒谬的,因为 PK 编号也是自动递增的,但在 django 管理器中无法自动填充或实际使用它。

    [更新:正如我在评论中所说,有一种方法可以为此使用主键,但它不会填充 before 保存字段]

    【讨论】:

    • 您确定此代码也适用于并发事务吗?如果两个请求同时执行count(),然后写入相同的值,会发生什么情况?
    • 确实如此……在我的用例中这并不重要,因为一次永远不会有两个请求……但即便如此,我也必须想出更好的方法来实现这一点。谢谢你的建议! :)
    • 你永远不能从这个表中删除任何东西,对吧?否则你会得到重复的代码。
    • 考虑使用Cliente.objects.aggregate(Max('clientcode')) 而不是Cliente.objects.count()。这样可以避免重复值问题。
    • 还可以考虑使用select_for_update 来防止并发请求出错。
    【解决方案2】:

    我也遇到过这个问题,我的实例是customer.number,它与客户Store 相关。我很想使用类似的东西:

    # Don't do this:
    
    class Customer(models.Model):
        # store = ...
        number = models.IntegerField(default=0)
    
        def save(self, *args, **kwargs):
            if self.number == 0:
                try:
                    self.number = self.store.customer_set.count() + 1
                else:
                    self.number = 1
            super(Customer, self).save(*args, **kwargs)
    

    以上可能会导致几个问题:假设有 10 个客户,我删除了 6 号客户。下一个要添加的客户将是(看似)第 10 个客户,然后它将成为第二个客户#10。 (这可能会导致get() 查询集中出现大错误)

    我最终得到的是这样的:

    class Store(models.Model):
        customer_number = models.IntegerField(default=1)
    
    class Customer(models.Model):
        store = models.ForeignKey(Store)
        number = models.IntegerField(default=0)
    
        def save(self, *args, **kwargs):
            if self.number == 0:
                self.number = self.store.customer_number
                self.store.number += 1
                self.store.save()
            super(Customer, self).save(*args, **kwargs)
    

    PS:

    您多次提出要在“之前”填写此字段。我想您希望在保存之前填写它,以便您可以访问它。对此我想说:此方法允许您访问store.customer_number 以查看下一个号码。

    【讨论】:

    • 尽管这可以解决重复问题,但如果我删除中间的条目,仍然会出现空白。不能用作表中元组的索引号。
    • 有没有办法生成连续的数字,最后一个数字的值应该等于count()。删除条目时所有数字都应该更新吗?我想这可以完成删除事件检测并使用循环更新所有条目。但我不知道如何在 django 模型中执行此操作。您能否编辑您的代码来解决这个问题..
    • 我所做的方法就像自动增量一样,它不会重复使用数字。您可以编写一个循环来更新数字,但可能不值得 [您的] 时间来编写该函数,也不值得 [计算机] 时间来运行它。即使是一个小型数据库,访问所有这些记录的时间也可能很长。
    • 是的,时间复杂度是个问题。也许这就是为什么如果数据被删除,自动增量字段也会出现空白!
    【解决方案3】:

    您的代码有错误,这就是您无法导入它的原因:

    from django.db import models
    class WhatEver(models.Model):
        number = models.IntegerField('Just a Field', default=0)
    

    Yuval A 关于自动递增是正确的:你甚至不需要声明这样的字段。只需使用pkid,它们的含义相同,除非模型中有复合pk:

    > w = Whatever(number=10)
    > w
    <Whatever object>
    > w.id
    None
    > w.save()
    > w.id
    1
    

    [update] 好吧,我还没有尝试将 callable 作为默认值。我认为如果你修复了这些错误,它一定可以工作。

    【讨论】:

    • 我认为对于 django 1.2.1 Field.default() 可以有一个可调用对象,而不仅仅是一个数字/字符串
    【解决方案4】:

    每个 Django 模型都已经有一个 auto-generated primary key:

    id = models.AutoField(primary_key=True)
    

    您似乎在尝试复制已经存在的行为,只需使用对象主键即可。

    【讨论】:

    • 我知道主键,但我必须在 django 管理页面中显示该数字。有什么办法吗?
    • 那行不通。如果你把它当作 AutoField django 崩溃。如果它是一个 IntegerField 它不能按预期工作。它只是变成一个普通的 IntegerField。我需要该字段自动填充下一个数字(我认为我很难解释自己)
    • 如果必须,只需添加另一个字段 AutoField,但不是主键。无论如何,听起来你做错了什么。
    • 模型中没有 primary_key=True 标志就不能使用 AutoField。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-23
    • 2014-02-03
    • 2013-04-24
    • 2010-09-29
    • 1970-01-01
    相关资源
    最近更新 更多