【发布时间】:2020-12-12 18:22:26
【问题描述】:
我有一个 db(sqlite),其中包含防火墙和策略规则定义。而且我需要将每条记录按顺序排列在他们的防火墙中。我的防火墙和 PolicyRule 模型关系是多对多的。所以我将排名(订单号)存储在关联模型中。即使我在记录中间插入数据,我怎样才能让它们保持有序?
例如:
我按以下顺序使用 order_by 获取记录:
1- Rule A
2- Rule B
3- Rule C
然后我想在规则B和规则C之间添加规则D。所以我的下一个查询结果必须是这样的:
1- Rule A
2- Rule B
3- Rule D
4- Rule C
我需要知道规则的确切顺序,因为我将它们应用于 iptables 并且 iptables 策略必须与用户的顺序完全相同。
这是我的模型:
class PolicyRule(db.Model):
__tablename__ = 'policy_rule'
id = db.Column(db.Integer(), primary_key=True)
active = db.Column('is_active', db.Boolean(), nullable=False, server_default='1')
name = db.Column(db.String(255, collation='NOCASE'), nullable=False, unique=True)
rule_type = db.Column(db.String(255, collation='NOCASE'), nullable=False) # IPv4 or IPv6
direction = db.Column(db.Text())
action = db.Column(db.Text())
comment = db.Column(db.Text())
log = db.Column(db.Boolean(), nullable=False, server_default='1')
firewalls = db.relationship("FwPolicyRules", back_populates="rule")
# Foreign key assignments for relationships
src_addr_id = db.Column(db.Integer(), db.ForeignKey(Address.id, ondelete='CASCADE'))
dst_addr_id = db.Column(db.Integer(), db.ForeignKey(Address.id, ondelete='CASCADE'))
src_service_id = db.Column(db.Integer(), db.ForeignKey(Service.id, ondelete='CASCADE'))
dst_service_id = db.Column(db.Integer(), db.ForeignKey(Service.id, ondelete='CASCADE'))
interface_id = db.Column(db.Integer(), db.ForeignKey(Interface.id, ondelete='CASCADE'))
time_profile_id = db.Column(db.Integer(), db.ForeignKey(TimeProfile.id, ondelete='CASCADE'))
# Relationship definitions for access the objects directly like "policy_rule.src_addr".
src_addr = db.relationship("Address", foreign_keys=[src_addr_id], lazy='subquery', backref=db.backref("policy_src_addr", uselist=True))
src_port = db.relationship("Service", foreign_keys=[src_service_id], lazy='subquery',backref=db.backref("policy_src_port", uselist=True))
dst_addr = db.relationship("Address", foreign_keys=[dst_addr_id], lazy='subquery',backref=db.backref("policy_dst_addr", uselist=True))
dst_port = db.relationship("Service", foreign_keys=[dst_service_id], lazy='subquery',backref=db.backref("policy_dst_port", uselist=True))
interface = db.relationship("Interface", foreign_keys=[interface_id], lazy='subquery',backref=db.backref("policy_interface", uselist=True))
time_profile = db.relationship("TimeProfile", foreign_keys=[time_profile_id], lazy='subquery',backref=db.backref("policy_time_profile", uselist=True))
class Firewall(db.Model):
__tablename__ = 'firewall'
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(255, collation='NOCASE'), nullable=False, unique=True)
policy_rules = db.relationship("FwPolicyRules", back_populates="firewall", lazy='subquery', cascade="delete-orphan")
nat_rules = db.relationship("FwNatRules", back_populates="firewall", lazy='subquery', cascade="delete-orphan")
routing_rules = db.relationship("FwRoutingRules", back_populates="firewall", lazy='subquery', cascade="delete-orphan")
interfaces = db.relationship('Interface', secondary=interfaces, lazy='subquery', backref=db.backref('used_firewalls', lazy=True, uselist=True))
class FwPolicyRules(db.Model):
__tablename__ = 'fw_policy_rules'
id = db.Column(db.Integer, primary_key=True)
firewall_id = db.Column(db.Integer, db.ForeignKey('firewall.id', ondelete='cascade'))
policy_rule_id = db.Column(db.Integer, db.ForeignKey('policy_rule.id', ondelete='cascade'))
rank = db.Column(db.Integer, autoincrement=True)
rule = db.relationship("PolicyRule", back_populates="firewalls", lazy='subquery')
firewall = db.relationship("Firewall", back_populates="policy_rules", lazy='subquery')
编辑:我认为尽管有很多解释,但没有人完全理解我的问题。要清楚,我想要这个的多对多版本: https://docs.sqlalchemy.org/en/13/orm/extensions/orderinglist.html
【问题讨论】:
-
不是一个正式的答案,但您使用 SQLite 遵循的一般模式是不担心 SQL 中数据的内部顺序。这是因为,一般来说,真的根本没有任何内部秩序。相反,如果您想以特定顺序查看您的数据,只需使用适当的
ORDER BY子句。并且,可能考虑使用索引调整查询,这也有助于排序步骤。 -
也许你的“rank”可能是一个浮点数而不是一个整数,所以如果你需要在两个现有记录之间插入一条新记录,你可以将它设置在它们的“rank”值之间。
标签: python sqlite flask sqlalchemy flask-sqlalchemy