【问题标题】:Django query assigns database columns to wrong model instance propertiesDjango 查询将数据库列分配给错误的模型实例属性
【发布时间】:2019-07-19 07:27:24
【问题描述】:

非常奇怪的问题 - 当我查询模型实例时,数据返回分配给错误的属性。

型号:

class SaleLineItem(models.Model):
    sale = models.ForeignKey(Sale, on_delete=models.CASCADE, related_name="sale_line_items")
    stock_unit = models.ForeignKey(StockUnit, on_delete=models.CASCADE, related_name="sale_line_items")

    currency = models.CharField(max_length=3)
    price_original = models.FloatField()
    price_paid = models.FloatField()

    tax_amount = models.FloatField(null=True, blank=True)

    num_sold = models.IntegerField()

    sale_line_item_id = models.CharField(max_length=30, null=True, blank=True)

    status = models.CharField(max_length=20, choices=SALE_STATUS_CHOICES, null=True, blank=True)

数据库行:

  id   | currency | price_original | price_paid | tax_amount | num_sold | sale_line_item_id |  status   | sale_id | stock_unit_id 
-------+----------+----------------+------------+------------+----------+-------------------+-----------+---------+---------------
 15726 | THB      |            130 |        130 |            |        1 |                   | delivered |   16219 |             2

还有查询:

sli = SaleLineItem.objects.get(pk=15726)
print(sli.pk)
-------------------------
16219

print(sli.stock_unit_id)
-------------------------
THB

print(sli.currency)
-------------------------
130.0

数据被填充到对象上,但所有内容都“移动”了一列。

但如果我这样查询:

SaleLineItem.objects.filter(pk=15726).values()
-------------------------
<QuerySet [{'id': 15726, 'sale_id': 16219, 'stock_unit_id': 2, 'currency': 'THB', 'price_original': 130.0, 'price_paid': 130.0, 'tax_amount': None, 'num_sold': 1, 'sale_line_item_id': None, 'status': 'delivered'}]>

。 . .结果是正确的。

我以为我可能有未迁移的模型,但我运行了两次 makemigrations 并且迁移没有效果。

当我使用较低级别的 QuerySet 方法时,结果相同:

qs = SaleLineItem.objects.all()
clone = qs._chain()
clone.query.add_q(Q(pk=15726))
print(clone)
------------------------------
<QuerySet [<SaleLineItem: SaleLineItem object (16219)>]>

注意模型__str__上的pk不正确。

有什么想法吗?

跑步:

Python 3.7.3 Django 2.2.1 Postgres 10

【问题讨论】:

    标签: django django-models django-queryset


    【解决方案1】:

    原来是因为我用一个额外的(非字段)参数覆盖了 __init__。

        @classmethod
        def from_db(cls, db, field_names, values):
            if len(values) != len(cls._meta.concrete_fields):
                values_iter = iter(values)
                values = [
                    next(values_iter) if f.attname in field_names else DEFERRED
                    for f in cls._meta.concrete_fields
                ]
            new = cls(*values)
            new._state.adding = False
            new._state.db = db
            return new
    

    使用 *values 将数据库值填充到模型中,并且模型需要特定顺序的字段。所以你不能在 __init__ 中有额外的参数,否则顺序会搞砸。

    编辑:

    未在文档中阅读此部分 (https://docs.djangoproject.com/en/2.1/ref/models/instances/):

    您可能想通过覆盖 __init__ 来自定义模型 方法。但是,如果您这样做,请注意不要更改呼叫 签名 。 . .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-23
      • 2023-03-30
      • 1970-01-01
      • 2023-03-27
      相关资源
      最近更新 更多