【问题标题】:Django model field default based on another model fieldDjango 模型字段默认基于另一个模型字段
【发布时间】:2015-09-26 09:29:08
【问题描述】:

我使用 Django Admin 来构建一个管理站点。有两张表,一张是ModelA,里面有数据,另一张是ModelB,里面什么都没有。如果ModelB中的一个模型字段b_b为None,则可以在网页上以ModelA的字段a_b的值显示。

不知道怎么弄,下面是伪代码:

在models.py中

from django.db import models

class ModelA(models.Model):
  a_a = models.CharField(max_length=6)
  a_b = models.CharField(max_length=6)

class ModelB(models.Model):
  modela = models.OneToOneField(ModelA)
  b_b = models.CharField(max_length=6, choices=[(1, 'M'), (2, 'F')], default=self.modela.a_b)

在 admin.py 中

from django.contrib import admin
from .models import ModelA, ModelB

class ModelBAdmin(admin.ModelAdmin):
  fields = ['b_b']
  list_display = ('b_b')

我认为如果 modelB 的 b_b 具有 modelA 的相对 a_b 值的默认值,我在 django 管理更改(编辑)页面中有一个默认值 b_b(View),它将数据关联到特定的 modelB 实例。

我想更轻松地在网页中填写 b_b。

不知道这个要求能不能达到?或者还有其他方法可以做到这一点?

我尝试自定义模板过滤器如下:

在模板/admin/includes/fieldset.html中

 {% load drop_null %}

    {% if field.is_checkbox %}
        {{ field.field }}{{ field.label_tag }}
    {% else %}
        {{ field.label_tag }}
        {% if field.is_readonly %}
            <p>{{ field.contents }}</p>
        {% else %}
            {% if field.field.name == 'b_b' %}
                {{ field|dropnull }}
            {% else %}
                {{ field.field }}
            {% endif %}
        {% endif %}
    {% endif %}

在模板标签/drop_null.py 中

from django import template
register = template.Library()

@register.filter(name='dropnull')
def dropnull(cls):
    return cls.modela.a_b

“字段”是 。它不是 ModelB 的一个实例。 如何获取 ModelB 实例?

【问题讨论】:

  • 我认为你真的需要重新评估你在这里想要达到的目标。 ModelA 会不会只有一行数据? self.modela 也不会像“self”一样工作,它是 ModelB 的实例。
  • 当您说“它可以显示在...的网页上”时,您指的是哪个网页?用于创建新 modelB 实例的管理表单或访问者将看到与特定 modelB 实例关联的数据的公共页面?
  • 我写了一个无法执行的伪代码。我希望 ModelB.b_b 有一个默认显示在管理页面上,管理员访问者将看到与特定 modelB 实例关联的数据。

标签: python django django-admin


【解决方案1】:

您可以为管理模板定义和注册一个自定义template filter

来自文档:https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/

【讨论】:

  • fieldset.html 中的“字段”是 。它不是 ModelB 的一个实例。如何获取 ModelB 实例?我在我问的原始问题中添加的细节。
【解决方案2】:

您可以覆盖 modelB 模型的 save 方法,而不是提供默认值:

class ModelB(models.Model):
    modela = models.OneToOneField(ModelA)
    b_b = models.CharField(max_length=6, choices=[(1, 'M'), (2, 'F')], blank=True)

    def save(self, *args, **kwargs):
        if not self.b_b:
            self.b_b = self.modela.a_b
        super(ModelB, self).save(*args, **kwargs)

在 cmets 中澄清后编辑

如果您只想向访问者显示值,但又想保持ModelB.b_b 为空这一事实,则逻辑应位于模板中。

假设您的视图集 objB 在上下文中是您有兴趣显示的 ModelB 对象,则模板的相关部分应如下所示:

{% with objB.b_b as bValue %}
{% if not bValue %}
    <p>{{ objB.modela.a_b }}</p>
{% else %}
    <p>{{ bValue }}</p>
{% endif %}
{% endwith %}

【讨论】:

  • 此保存方法是否覆盖 ModelB 实例的保存操作?我不需要保存,我只需要在视图页面中的 ModelB 实例中显示一个默认值。我要轻松填b_b
  • 我觉得你修改模板的想法是对的。我发现 django 管理模板的路径是 /usr/local/lib/python2.7/dist-packages/django/contrib/admin/templates/admin/change_form.html。我应该尝试修改这个抽象文件吗?
  • 当您添加 cmets 时,我对您想要实现的目标越来越感到困惑。您说您希望在“访问者将看到与特定 modelB 实例关联的数据的公共页面”上进行值替换,而这里您正在谈论管理模板。这对我来说没有意义。
  • 对不起,我脑子里有些误会。我的意思是管理页面。
猜你喜欢
  • 2011-05-21
  • 2016-01-02
  • 2014-12-25
  • 2016-04-19
  • 2019-03-11
  • 1970-01-01
  • 2021-10-09
  • 1970-01-01
  • 2020-06-23
相关资源
最近更新 更多