很好的pythonic方式来指定django模型字段选择与额外的属性和方法 [英] Nice pythonic way to specify django model field choices with extra attributes and methods

查看:133
本文介绍了很好的pythonic方式来指定django模型字段选择与额外的属性和方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在django模型中指定选项,以便选择具有比数据库值和显示值更多的信息(根据 django的选择规格)?假设不同的选择有一些我想要设置的配置选项(在代码中)以及一些方法,并且方法可能在不同的选择之间有所不同。以下是一个例子:

How can you specify choices on a django model such that the "choice" carries more information than just the database value and display value (as required by django's choices spec)? Suppose the different choices have a number of config options that I want to set (in code) as well as some methods, and the methods may be different between different choices. Here's an example:

class Reminder(models.Model):
    frequency = models.CharField(choices=SOME_CHOICES)
    next_reminder = models.DateTimeField()
    ...

为每周和每月提醒指定SOME_CHOICES?到目前为止,我最好的解决方案是为每个频率选择编写一个类,并将类名存储在数据库中,然后在需要方法或配置数据时按名称导入类。

How should we specify SOME_CHOICES for something like "weekly" and "monthly" reminders? So far my best solution is to write a class for each frequency choice, and store the class name in the database and then import the class by name whenever I need the methods or config data.

理想情况下,我想指定所有这些配置值,并在一个位置定义每个选项的方法,而不是将逻辑分散在一堆模型具有long if / elif / elif ... else结构的方法。 Python是面向对象的...这些频率选择似乎有数据和方法,所以他们似乎是类似的好候选人...

Ideally I would like to specify all of these config values and define the methods for each choice all in one place, rather than have the logic scattered all over a bunch of Model methods with long if/elif/elif...else structures. Python is object-oriented... these frequency choices seem to have "data" and "methods" so they seem like good candidates for classes...

class ReminderFrequency(object):
    pass

class Weekly(ReminderFrequency):
    display_value = "Every week"

    def get_next_reminder_time(self):
        return <now + 7 days>

class Monthly(ReminderFrequency):
    display_value = "Every month"

    def get_next_reminder_time(self):
        return <now + 1 month>

SOME_CHOICES = ((freq.__name__, freq.display_value) for freq in [Weekly, Monthly])

假设除了 get_next_reminder_time 之外,我想指定一些类似 first_reminder (让我们说每周一次,你的第一个提醒来自三天后,下一个7天之后,但是对于每月,第一次提醒是从现在起7天,之后的下一个月等)。另外还有5个依赖于选择的其他配置值或方法。

And suppose that in addition to get_next_reminder_time, I want to specify something like first_reminder (let's say for "weekly" your first reminder comes three days from now, and the next one 7 days after that, but for "monthly", the first reminder comes 7 days from now, and the next one month after that, etc). Plus 5 other config values or methods that depend on the choice.

一个想法是使频率一个FK某些其他模型频率我在哪里设置配置值,但这不允许不同的选择有不同的方法或逻辑(如每周对每月的例子)。所以这就是出来。

One thought is to make frequency a FK to some other model Frequency where I set the config values, but that does not allow different choices to have different methods or logic (like the weekly vs monthly example). So that's out.

由于需要根据存储在数据库中的类名称的名称加载每个ReminderFrequency子类,所以我目前的方法感觉很麻烦。任何其他想法?或者这是正确和好的诡计方式?

My current approach feels very cumbersome because of the requirement to load each ReminderFrequency subclass by name according to the class name stored in the database. Any other ideas? Or is this "the Right and Good Pythonic Way"?

推荐答案

我认为在Django中最自然的处理方式将是创建一个自定义模型字段。您将使用

I think the most natural way of handling this in Django would be to create a custom model field. You would use it like so:

class Reminder(models.Model):
    frequency = models.FrequencyField()
    next_reminder = models.DateTimeField()

reminder = Reminder.objects.get()
reminder_time = reminder.frequency.get_next_reminder_time()

实现,请查看相关文档。简单来说,你可能会:

To implement it, review the relevant documentation. Briefly, you'd probably:

  • Inherit from CharField
  • Supply the choices in the field definition
  • Implement get_prep_value(). You could represent values as actual class names, like you have above, or by some other value and use a lookup table.
  • Implement to_python(). This is where you'll convert the database representation into an actual Python instance of your classes.

但不是太多。

(以上假设您想要在代码中定义行为,如果需要通过向数据库提供配置值来配置行为(就像您上面提到的 ForeignKey 想法)这是另一个故事。)

(The above assumes that you want to define the behavior in code. If you need to configure the behavior by supplying configuration values to the database (as you suggested above with the ForeignKey idea) that's another story.)

这篇关于很好的pythonic方式来指定django模型字段选择与额外的属性和方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆