在Django中动态创建选项

0 投票
1 回答
31 浏览
提问于 2025-04-14 16:48

我正在尝试在Django表单中动态填充选项,这些选项来自一个外部的API。
到目前为止,我的模型是这样的:

from django.db import models

class MyModel(models.Model):

choice_field = models.CharField(max_length=100, choices=())

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    
    api_url = 'http://api.com'
    response = requests.get(api_url)
    if response.status_code == 200:
        
        data = response.json()
        options = [(option['value'], option['label']) for option in data]
       
        self._meta.get_field('choice_field').choices = options

不过,这个方法没有成功,有人能帮我吗?

1 个回答

0

如果你能使用Django 5.0,可以参考文档中的内容:

你可以把选择项定义为一个不需要参数的可调用对象(也就是一个函数),这个函数会返回上面提到的任何格式。比如:

def get_currencies():
    return {i: i for i in settings.CURRENCIES}


class Expense(models.Model):
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    currency = models.CharField(max_length=3, choices=get_currencies)

把一个可调用对象作为choices传入特别有用,尤其是当这些选择项是:

一些输入输出操作的结果(这些结果可能会被缓存),比如查询同一个数据库或外部数据库中的表,或者从静态文件中获取选择项。还有一种情况是,选择项的列表大部分时间是稳定的,但偶尔会有所变化,或者在不同的项目中会有所不同。这个类别的例子包括使用一些第三方应用,它们提供了一些众所周知的值,比如货币、国家、语言、时区等等。

所以你基本上可以这样做:

def get_choices:
    api_url = 'http://api.com'
    response = requests.get(api_url)
    if response.status_code == 200:
        data = response.json()
        return [(option['value'], option['label']) for option in data]
    else:
        pass #error handling here

#---------------------------------

from django.db import models

class MyModel(models.Model):
     choice_field = models.CharField(max_length=100, choices=get_choices)

另外,文档中还有一点需要注意:

要注意,选择项可以是任何序列对象——不一定非得是列表或元组。这让你可以动态构建选择项。但如果你发现自己在拼凑动态的choices,那么你可能更适合使用一个合适的数据库表和ForeignKeychoices是用来存放那些不怎么变化的静态数据的。

撰写回答