Django模型字段默认值基于另一个模型字段

6

我使用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。

我不知道是否可以实现此要求?还是有其他方法可以实现?

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

在templates/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 %}

在templatetags/drop_null.py文件中。
from django import template
register = template.Library()

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

'field' 是一个 < django.contrib.admin.helpers.AdminField object at 0x3cc3550>,它不是 ModelB 的实例。如何获得 ModelB 的实例?

我认为你真的需要重新评估你在这里尝试实现什么。ModelA只会有一行数据吗?此外,self.modela不起作用,因为"self"是ModelB的实例。 - djangoat
当你说“它可以在网页上显示…”时,你指的是哪个网页?是创建新的modelB实例的管理员表单,还是访客将看到与特定modelB实例相关联的数据的公共页面? - 301_Moved_Permanently
我编写了一段无法执行的伪代码。我希望ModelB.b_b有一个默认值,在管理员访问者查看与特定ModelB实例关联的数据时能够显示在管理页面上。 - Jameson
2个回答

1
你可以重写你的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)

在评论中澄清后进行编辑

如果您只想向访问者显示值,但希望保留 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 %}

这个 save 方法会覆盖 ModelB 实例的保存操作吗?我不需要保存,我只需要在视图页面中显示 ModelB 实例的默认值。我想要轻松地填充 b_b。 - Jameson
我认为你修改模板的想法是正确的。我发现Django管理模板的路径是/usr/local/lib/python2.7/dist-packages/django/contrib/admin/templates/admin/change_form.html。我应该尝试修改这个抽象文件吗? - Jameson
随着您添加注释,我对您想要实现的目标越来越困惑。您说您想在“公共页面上,访问者将看到与特定modelB实例相关联的数据”上进行值替换,但这里您正在谈论管理员模板。这对我来说没有意义。 - 301_Moved_Permanently
抱歉,我的理解有些误差。我指的是管理员页面。 - Jameson

0

'fieldset.html' 中的 'field' 是 <django.contrib.admin.helpers.AdminField object at 0x3cc3550>。它不是 ModelB 的实例。 我该如何获取 ModelB 实例?这是我添加到原来问题中的细节。 - Jameson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接