Django 3 主键问题

Django 3 primary key issues

我的 Django 模型有问题,主要是主键问题。

我使用管理界面来管理我的数据。我已经建立了一个由 3 个主键组成的数据库,以减少多个条目 (yearmonthbnr)。

但是我的模型中没有涵盖这一点,因为 django 只接受一个主键。我尝试了一些东西,但 none 对我有帮助。管理界面总是给我一个错误。

  1. 删除模型中的所有主键
  2. 试图在我的 model/Database 中添加 ID 列,但未在我的数据库中声明为主键
  3. 添加了unique_together

现在我的模型是这样的:

class BalBalance(models.Model):
    month = models.PositiveIntegerField(default=datetime.datetime.now().month, validators=[MinValueValidator(1), MaxValueValidator(12)])
    year = models.PositiveIntegerField(default=datetime.datetime.now().year, validators=[MinValueValidator(1990), MaxValueValidator(datetime.datetime.now().year)])
    bnr = models.ForeignKey('BalBankaccount', models.DO_NOTHING, db_column='BNR')  # Field name made lowercase.
    balance = models.DecimalField(db_column='BALANCE', max_digits=10, decimal_places=2)  # Field name made lowercase.
    available_balance = models.DecimalField(db_column='AVAILABLE_BALANCE', max_digits=10, decimal_places=2)  # Field name made lowercase.
    unavailable_balance = models.DecimalField(db_column='UNAVAILABLE_BALANCE', max_digits=10, decimal_places=2)  # Field name made lowercase.
    date_checked = models.DateTimeField(db_column='DATE_CHECKED')  # Field name made lowercase.
    created_at = models.DateTimeField(db_column='CREATED_AT')  # Field name made lowercase.

    class Meta:
        managed = False
        db_table = 'BAL_BALANCE'
        unique_together = (('month', 'year', 'bnr'),) 

我的 admin.py 看起来像这样

    from django.contrib import admin
    from .models import *
    
    # Register your models here.
    myModels = [BalBankaccount,BalCompany,BalIncome,BalInstitution,BalLocation]
    admin.site.register(myModels)
    
    class BalBalanceAdmin(admin.ModelAdmin):
        list_display = ('month','year','bnr','balance','available_balance','unavailable_balance')
        list_filter = ('bnr',)
        ordering = ('year','month')
        search_fields = ('bnr',)
    
    admin.site.register(BalBalance,BalBalanceAdmin)

我怎样才能摆脱这个问题?感谢任何帮助

编辑:根据现有的内容或我测试的内容,django 会抛出不同的错误:

如果我自己声明 primary_key,我会得到如下内容:

get() returned more than one BalBalance -- it returned 12!.

Get 只允许 return 1 个对象,但在这种情况下它 returns 12 个对象,因为我不允许在 django 中将我的 3 PK 声明为 PK...

如果我尝试通过添加 ID 来处理此错误,django 会抛出一个错误,指出字段 ID 丢失或存在完整性错误:

IntegrityError at /admin/balance/balbalance/add/ (1364, "Field 'ID' doesn't have a default value")

如果我理解您收到的最后一个 (IntegrityError) 错误,我认为这是因为您手动添加了一个 id 字段作为主键。不要这样做,因为 Django 会自动为您创建一个自动递增的 id 主键,对于您自己没有 'override' 主键的任何模型。

因此请删除您添加的任何 'id' 或主键字段,然后将您的 unique_together 添加到元数据中。如果您 makemigrationsmigrate,这应该会按预期工作,并且您应该能够 BalBalance.objects.get(month=x, year=y, bnr=z) 并且可靠地只得到一个结果。这 实际上 与在所有 3 个字段中使用主键的初衷相同。

编辑:根据您的评论,我现在看到了潜在的问题,我没有注意到您在模型的 Meta 中设置了 managed=False。这意味着 django 不会为您 create/modify 而 table,因此上面建议的更改不会对结构产生任何影响。大概你有这个,因为你现在希望在 Django 管理界面中看到(并可能操作)现有 table 中的现有数据。

所以问题归结为:

  1. Django 将假设(除非您指定一个单独的字段作为主键)您已经在 table 上有一个自动递增的 id 列。你的 table.
  2. 上没有这个
  3. Django 不支持跨多个字段的主键,这是您在 table
  4. 上所拥有的

因此,解决方案(可能会让您很烦)是使数据库与 python 中定义的模型结构相匹配,使用我之前建议的结构。

因此:不要在模型上指定PK(Django会假设它有一个id列),然后手动操作数据库中的table添加一个自动递增的id列(和将其设置为主键,从其他 3 个字段中删除 PK)。接下来,在模型中的其他 3 个字段上指定 unique_together,然后添加并在数据库中的这些字段中添加唯一键。

一旦数据库反映了模型定义,您的痛苦就应该消除,管理员应该按预期使用您粘贴在问题中的代码。

当然,这取决于您是否将其他软件连接到该数据库 table,以及这些软件如何依赖 PK...您可能会遇到这些问题,但我不能肯定地说.