我有一个声明性映射:
class User(base):
username = Column(Unicode(30), unique=True)
如何判断sqlalchemy是否可以修改此属性? 我想出的解决方法很简单:
from werkzeug.utils import cached_property
# regular @property works, too
class User(base):
_username = Column('username', Unicode(30), unique=True)
@cached_property
def username(self):
return self._username
def __init__(self, username, **kw):
super(User,self).__init__(**kw)
self._username=username
在数据库列权限级别执行此操作将不起作用,因为并非所有数据库都支持该功能。
答案 0 :(得分:1)
我可以建议以下方法保护列不被修改:
首先在设置任何属性时使用钩子:
如果上面的Base
声明的所有表中的所有列都将被挂钩,那么您需要以某种方式存储有关是否可以修改列的信息。例如,您可以继承sqlalchemy.Column类以向其添加一些属性,然后检查钩子中的属性。
class Column(sqlalchemy.Column):
def __init__(self, *args, **kwargs):
self.readonly = kwargs.pop("readonly", False)
super(Column, self).__init__(*args, **kwargs)
# noinspection PyUnusedLocal
@event.listens_for(Base, 'attribute_instrument')
def configure_listener(class_, key, inst):
"""This event is called whenever an attribute on a class is instrumented"""
if not hasattr(inst.property, 'columns'):
return
# noinspection PyUnusedLocal
@event.listens_for(inst, "set", retval=True)
def set_column_value(instance, value, oldvalue, initiator):
"""This event is called whenever a "set" occurs on that instrumented attribute"""
logging.info("%s: %s -> %s" % (inst.property.columns[0], oldvalue, value))
column = inst.property.columns[0]
# CHECK HERE ON CAN COLUMN BE MODIFIED IF NO RAISE ERROR
if not column.readonly:
raise RuntimeError("Column %s can't be changed!" % column.name)
return value
要挂钩具体属性,您可以采用下一种方式(不需要向列中添加属性):
# standard decorator style
@event.listens_for(SomeClass.some_attribute, 'set')
def receive_set(target, value, oldvalue, initiator):
"listen for the 'set' event"
# ... (event handling logic) ...
Here是关于SQLAlchemy事件的指南。
我建议的第二种方法是使用您在问题中显示的标准Python属性或SQLAlchemy hybrid_property
,但使用此方法会导致代码增长。
P.S。我认为紧凑的方法是将属性添加到列并挂钩所有设置事件。
答案 1 :(得分:1)
您可以使用validates
SQLAlchemy功能。
from sqlalchemy.orm import validates
...
class User(base):
...
@validates('username')
def validates_username(self, key, value):
if self.username: # Field already exists
raise ValueError('Username cannot be modified.')
return value
参考:https://docs.sqlalchemy.org/en/13/orm/mapped_attributes.html#simple-validators
答案 2 :(得分:0)
对@AlexQueue 的回答稍作修正。
#include <iostream>
#include <SFML/Graphics.hpp>
int WIDTH = 600;
int HEIGHT = 600;
int main(){
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "Pokemon");
sf::Event event;
sf::Font font;
font.loadFromFile("arial.ttf");
sf::Text start("Hello! What?", font, 300);
start.setPosition(100, 100);
while(window.isOpen()){
window.setFramerateLimit(30);
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed){
window.close();
}
}
window.clear(sf::Color::Blue);
window.draw(start);
window.display();
}
return EXIT_SUCCESS;
}