Rules是一個很小但功能強大的應用程序,爲Django提供對象級權限,而不須要數據庫。它的核心是構建基於規則的系統的通用框架,相似於決策樹。它還能夠在其餘上下文和框架中用做獨立的庫。html
rules has got you covered. rules is:python
rules須要python 2.7/3.4或更高版本。它能夠選擇與Django集成,在這種狀況下須要Django 1.11或更高版本。.git
Note: At any given moment in time, rules will maintain support for all currently supported Django versions, while dropping support for those versions that reached end-of-life in minor releases. See the Supported Versions section on Django Project website for the current state and timeline.github
使用pip:web
$ pip install rules
手動安裝:數據庫
$ git clone https://github.com/dfunckt/django-rules.git
$ cd django-rules
$ python setup.py install
執行測試:django
$ ./runtests.sh
你可能須要閱讀 Best practices 以得到有關如何使用 rules的通常性建議。編程
INSTALLED_APPS = ( # ... 'rules', )
AUTHENTICATION_BACKENDS = ( 'rules.permissions.ObjectPermissionBackend', 'django.contrib.auth.backends.ModelBackend', )
rules基於這樣的思想: 你維護一個RuleSet類對象(相似dict),至關於一個映射表,由字符串標識到Predicate類對象的映射後端
暫時忽略 rule sets,先定義一個 Predicate對象. 最簡單的方法是經過 @predicate 裝飾器:api
>>> @rules.predicate >>> def is_book_author(user, book): ... return book.author == user ... >>> is_book_author <Predicate:is_book_author object at 0x10eeaa490>
若是書的做者是給定的user,This predicate 將返回 True ,不然返回 False.
Predicates 能被建立 經過 接收任意數量的位置參數的可調用對象:
這是它們的通常形式。若是從Django的受權角度來看,等效簽名爲
Predicates能夠對給定的參數執行任何操做,但若是它們檢查的條件爲真,則必須始終返回真,不然返回假。規則附帶了幾個預約義的謂詞,您稍後可能會在 API Reference,中瞭解到這些謂詞,這些謂詞在處理authorization in Django.時很是有用。
假設咱們想讓做者編輯或刪除他們的書,而不是其餘做者寫的書。因此,本質上,決定一個做者是否能夠編輯或刪除一本給定的書的是他們是不是做者。
在rules中,這些需求被當作rules。一個rule是惟一標識符(例如「can edit」)到predicate的映射。許多規則被組合成一個rule set。rules有兩個預約義的rule set::
So, 讓咱們定義第一組rules, 添加他們到共享的rule set. 咱們可使用以前定義過的 is_book_author謂詞對象:
>>> rules.add_rule('can_edit_book', is_book_author) >>> rules.add_rule('can_delete_book', is_book_author)
假設咱們有一些數據,咱們如今能夠測試咱們的規則:
>>> from django.contrib.auth.models import User >>> from books.models import Book >>> book1 = Book.objects.get(isbn='978-1-4302-1936-1') >>> book1.author <User: Tom> >>> author_tom = User.objects.get(username='Tom') >>> rules.test_rule('can_edit_book', author_tom, book1) True >>> rules.test_rule('can_delete_book', author_tom, book1) True
Nice… but not awesome(棒).
Predicates自己並無那麼有用——比任何其餘函數都沒那麼有用。然而,Predicates可使用二元運算符組合以建立更復雜的謂詞。謂詞支持如下運算符:
假設容許用戶編輯一本給定的書的要求是他們要麼是書的做者,要麼是「編輯」組的成員。容許用戶刪除一本書仍然應該由用戶是不是書的做者來決定。
使用易於實現的規則。咱們必須定義另外一個謂詞,若是給定的用戶是「editors」組的成員,則返回true,不然返回false。內置的is_group_member 工廠將派上用場:
>>> is_editor = rules.is_group_member('editors') # 是否是某個角色 >>> is_editor <Predicate:is_group_member:editors object at 0x10eee1350>
咱們能夠將它與 is_book_author謂詞進行合併,來建立一個新謂詞來檢查他們其中之一是否成立:
>>> is_book_author_or_editor = is_book_author | is_editor >>> is_book_author_or_editor <Predicate:(is_book_author | is_group_member:editors) object at 0x10eee1390>
咱們如今能夠更新 can_edit_book 規則:
>>> rules.set_rule('can_edit_book', is_book_author_or_editor) >>> rules.test_rule('can_edit_book', adrian, guidetodjango) True >>> rules.test_rule('can_delete_book', adrian, guidetodjango) True
讓咱們測試一下,若是換其餘用戶會怎麼樣:
>>> martin = User.objects.get(username='martin') >>> list(martin.groups.values_list('name', flat=True)) ['editors'] >>> rules.test_rule('can_edit_book', martin, guidetodjango) True >>> rules.test_rule('can_delete_book', martin, guidetodjango) False
很棒.
到目前爲止,咱們只使用了底層的通用框架來定義和測試規則。這一層根本不特定於Django;它能夠在任何上下文中使用。實際上,整個應用程序中沒有任何與django相關的導入(rules.templateTags模塊除外)。可是,規則能夠與Django緊密集成以提供受權。So far, we’ve only used the underlying, generic framework for defining and testing rules. This layer is not at all specific to Django; it may be used in any context. There’s actually no import of anything Django-related in the whole app (except in the rules.templatetags module). rules however can integrate tightly with Django to provide authorization.
rules能在Django中提供對象級別的權限控制,它附帶了一個受權後端和幾個用於模板中模板tags。
rules is able to provide object-level permissions in Django. It comes with an authorization backend and a couple template tags for use in your templates.
在rules中,permissions是特定類型的rules,你仍可經過建立或合併謂詞來定義他們,那些規則必須添加到權限指定的rule set以便rules認證後端能提取到
In rules, permissions are a specialised type of rules. You still define rules by creating and combining predicates. These rules however, must be added to a permissions-specific rule set that comes with rules so that they can be picked up by the rules authorization backend.
Django中命名權限的約定是app_label.action_object,咱們但願遵照這個約定。讓咱們爲書籍添加規則。更改書籍和書籍。刪除書籍權限:
The convention for naming permissions in Django is app_label.action_object, and we like to adhere to that. Let’s add rules for the books.change_book and books.delete_book permissions:
>>> rules.add_perm('books.change_book', is_book_author | is_editor) >>> rules.add_perm('books.delete_book', is_book_author)
看到API的區別了嗎?add_perm 將添加到permissions-specific rule set,而add_rule 將添加到 default shared rule set。可是,重要的是要知道這兩個規則集是分開的,這意味着在其中一個添加的rule不會在另外一個裏可用。
See the difference in the API? add_perm adds to a permissions-specific rule set, whereas add_rule adds to a default shared rule set. It’s important to know however, that these two rule sets are separate, meaning that adding a rule in one does not make it available to the other.
讓咱們檢查一下adrian 用戶對guidetodjango 書籍的修改權限
Let’s go ahead and check whether adrian has change permission to the guidetodjango book:
>>> adrian.has_perm('books.change_book', guidetodjango) False
當您調用User.has_perm方法時,django會詢問每一個在settings.authentication-backends裏的認證後端,用戶是否具備對象的給定權限。當查詢對象權限時,Django的默認認證後端始終返回false。rules帶有一個認證後端,它能夠經過查看 permissions-specific rule set來提供對象級權限。
讓咱們在設置中添加rules認證後端:
When you call the User.has_perm method, Django asks each backend insettings.AUTHENTICATION_BACKENDS whether a user has the given permission for the object. When queried for object permissions, Django’s default authentication backend always returns False. rules comes with an authorization backend, that is able to provide object-level permissions by looking into the permissions-specific rule set.
Let’s add the rules authorization backend in settings:
AUTHENTICATION_BACKENDS = ( 'rules.permissions.ObjectPermissionBackend', 'django.contrib.auth.backends.ModelBackend', )
Now, checking again gives adrian the required permissions:
如今再次檢查adrian 的對象權限
>>> adrian.has_perm('books.change_book', guidetodjango) True >>> adrian.has_perm('books.delete_book', guidetodjango) True >>> martin.has_perm('books.change_book', guidetodjango) True >>> martin.has_perm('books.delete_book', guidetodjango) False
注意:本節中描述的特性僅適用於Python3+。
NOTE: The features described in this section work on Python 3+ only.
對於一個model有一組權限是很常見的,好比Django用它的默認模型權限(如添加、更改等)提供的權限。當使用rules做爲權限檢查後端時,可使用新的meta選項以相似的方式聲明任何model的對象級權限。
It is common to have a set of permissions for a model, like what Django offers with its default model permissions (such as add, change etc.). When using rules as the permission checking backend, you can declare object-level permissions for any model in a similar way, using a new Meta option.
首先,您須要將model的基類和元類切換到rules.contrib.models中提供的稍微擴展的版本。有幾個classes和mixins可使用,這取決於您是否已經爲您的模型使用了自定義的基和/或元類。擴展很是小,除了使其註冊權限以外,不會以任何方式影響model的行爲。
First, you need to switch your model’s base and metaclass to the slightly extended versions provided in rules.contrib.models. There are several classes and mixins you can use, depending on whether you’re already using a custom base and/or metaclass for your models or not. The extensions are very slim and don’t affect the models’ behavior in any way other than making it register permissions.
若是您正使用django.db.models.model做爲您的model的基類,只需切換到RulesModel,就能夠很好地使用了。
若是您已經有了一個向model添加公共功能的自定義基類,請將RulesModelMixin添加到它繼承的類中,並將RulesModelBase設置爲它的元類,以下所示:
If you’re using the stock django.db.models.Model as base for your models, simply switch over to RulesModel and you’re good to go.
If you already have a custom base class adding common functionality to your models, add RulesModelMixin to the classes it inherits from and set RulesModelBase as its metaclass, like so:
from django.db.models import Model from rules.contrib.models import RulesModelBase, RulesModelMixin class MyModel(RulesModelMixin, Model, metaclass=RulesModelBase): ...
If you’re using a custom metaclass for your models, you’ll already know how to make it inherit from RulesModelBaseMixin yourself.
Then, create your models like so, assuming you’re using RulesModel as base directly:
若是您正在爲model使用自定義元類,那麼您就已經知道如何讓它從RulesModelBaseMixin繼承。
而後,像這樣建立模型,假設您直接使用RulesModel做爲基類:
import rules from rules.contrib.models import RulesModel class Book(RulesModel): class Meta: rules_permissions = { "add": rules.is_staff, "read": rules.is_authenticated, }
This would be equivalent to the following calls:
這至關於如下調用:
rules.add_perm("app_label.add_book", rules.is_staff) rules.add_perm("app_label.read_book", rules.is_authenticated)
RulesModelMixin中有一些方法能夠覆蓋,以便自定義如何註冊模型的權限。若是須要,請參閱文檔化的源代碼以瞭解詳細信息。
特別感興趣的是RulesModelMixin的get_perm 類方法,它能夠用於將權限類型轉換爲相應的完整權限名稱。若是須要以編程方式查詢給定模型的某種類型的權限,這很方便:
There are methods in RulesModelMixin that you can overwrite in order to customize how a model’s permissions are registered. See the documented source code for details if you need this.
Of special interest is the get_perm classmethod of RulesModelMixin, which can be used to convert a permission type to the corresponding full permission name. If you need to query for some type of permission on a given model programmatically, this is handy:
if user.has_perm(Book.get_perm("read")): ...
rules附帶了一組裝飾器來幫助您在視圖中強制受權。
rules comes with a set of view decorators to help you enforce authorization in your views.
對於基於函數的視圖,可使用permission_required裝飾器:
For function-based views you can use the permission_required decorator:
from django.shortcuts import get_object_or_404 from rules.contrib.views import permission_required from posts.models import Post def get_post_by_pk(request, post_id): return get_object_or_404(Post, pk=post_id) @permission_required('posts.change_post', fn=get_post_by_pk) def post_update(request, post_id): # ...
用法是直截了當的,可是在上面的示例中有一件事是突出的,這就是get_post_by_pk 函數。此函數給定當前請求和傳遞給視圖的全部參數,負責獲取和返回要檢查權限的對象,POST對象中的主鍵等於給定的post_id。這個特定的用例是很是常見的,因此爲了節省一些輸入,rules附帶了一個通用的助手函數,您可使用它來聲明性地完成這項工做。下面的例子至關於上面的例子:
Usage is straight-forward, but there’s one thing in the example above that stands out and this is the get_post_by_pk function. This function, given the current request and all arguments passed to the view, is responsible for fetching and returning the object to check permissions against – i.e. the Post instance with PK equal to the given post_id in the example. This specific use-case is quite common so, to save you some typing, rules comes with a generic helper function that you can use to do this declaratively. The example below is equivalent to the one above:
from rules.contrib.views import permission_required, objectgetter from posts.models import Post @permission_required('posts.change_post', fn=objectgetter(Post, 'post_id')) def post_update(request, post_id): # ...
有關decorator和helper函數的詳細信息,請參閱rules.contrib.views模塊。
For more information on the decorator and helper function, refer to the rules.contrib.views module.
Django包含一組訪問混合函數,您能夠在基於類的視圖中使用它們來強制受權。rules 擴展了這個框架,經過mixin提供對象級權限,PermissionRequiredMixin。
下面的示例將針對視圖的get_object 方法返回的實例自動測試權限:
Django includes a set of access mixins that you can use in your class-based views to enforce authorization. rules extends this framework to provide object-level permissions via a mixin, PermissionRequiredMixin.
The following example will automatically test for permission against the instance returned by the view’s get_object method:
from django.views.generic.edit import UpdateView from rules.contrib.views import PermissionRequiredMixin from posts.models import Post class PostUpdate(PermissionRequiredMixin, UpdateView): model = Post permission_required = 'posts.change_post'
您能夠經過覆蓋get_object 或get_permission_object來自定義對象。
有關更多信息,請參閱django文檔和rules.contrib.views模塊。
You can customise the object either by overriding get_object or get_permission_object.
For more information refer to the Django documentation and the rules.contrib.views module.
若是您使用rules.contrib.models提供的機制來註冊模型的權限(如Permissions in models中所述),那麼對於基於類的視圖,還有另外一種方便的混合方法。
rules.contrib.views.AutoPermissionRequiredMixin能夠識別使用的視圖類型,並自動檢查相應的權限。
若是應用標籤爲"posts",則此示例視圖將在不進行任何進一步配置的狀況下自動檢查 "posts.change_post"權限:
If you use the mechanisms provided by rules.contrib.models to register permissions for your models as described in Permissions in models, there’s another convenient mixin for class-based views available for you.
rules.contrib.views.AutoPermissionRequiredMixin can recognize the type of view it’s used with and check for the corresponding permission automatically.
This example view would, without any further configuration, automatically check for the "posts.change_post" permission, given that the app label is "posts":
from django.views.generic import UpdateView from rules.contrib.views import AutoPermissionRequiredMixin from posts.models import Post class UpdatePostView(AutoPermissionRequiredMixin, UpdateView): model = Post
默認狀況下,django.views.generic中的通用CRUD視圖映射到本機django權限類型(add、change、delete和view)。可是,當子類化autopermissionRequiredMixin時,能夠擴展、更改或替換預約義的映射。有關如何正確執行此操做的詳細信息,請參閱徹底文檔化的源代碼。
By default, the generic CRUD views from django.views.generic are mapped to the native Django permission types (add, change, delete and view). However, the pre-defined mappings can be extended, changed or replaced altogether when subclassing AutoPermissionRequiredMixin. See the fully documented source code for details on how to do that properly.
規則帶有兩個模板標記,容許您測試模板中的rules和permissions。
rules comes with two template tags to allow you to test for rules and permissions in templates.
Add rules to your INSTALLED_APPS:
INSTALLED_APPS = ( # ... 'rules', )
Then, in your template:
{% load rules %} {% has_perm 'books.change_book' author book as can_edit_book %} {% if can_edit_book %} ... {% endif %} {% test_rule 'has_super_feature' user as has_super_feature %} {% if has_super_feature %} ... {% endif %}
若是您在Django中設置了要與permissions一塊兒使用的rules,使用rules 在Admin中認證add/change/delete。Admin要求四種不一樣的權限:
If you’ve setup rules to be used with permissions in Django, you’re almost set to also use rules to authorize any add/change/delete actions in the Admin. The Admin asks for four different permissions, depending on action:
注意:view_permission在Django v2.1中是新的。
前四個很明顯。第五個是在管理員的「儀表板」中顯示應用程序所需的權限。如下是咱們虛構的 books 應用程序的一些規則示例:
Note: view permission is new in Django v2.1.
The first four are obvious. The fifth is the required permission for an app to be displayed in the Admin’s 「dashboard」. Here’s some rules for our imaginary books app as an example:
>>> rules.add_perm('books', rules.always_allow) >>> rules.add_perm('books.add_book', is_staff) >>> rules.add_perm('books.view_book', is_staff | has_secret_access_code) >>> rules.add_perm('books.change_book', is_staff) >>> rules.add_perm('books.delete_book', is_staff)
django-admin不支持對象權限,從這個意義上說,它永遠不會請求對對象執行操做的權限,只容許用戶對模型的(任何)實例執行操做。
若是要告訴Django用戶是否對特定對象具備權限,則必須重寫模型的ModelAdmin的如下方法:
Django Admin does not support object-permissions, in the sense that it will never ask for permission to perform an action on an object, only whether a user is allowed to act on (any) instances of a model.
If you’d like to tell Django whether a user has permissions on a specific object, you’d have to override the following methods of a model’s ModelAdmin:
rules帶有一個自定義的ModelAdmin 子類rules.contrib.admin.ObjectPermissionsModelAdmin,它重寫這些方法以將編輯的模型實例傳遞到受權後端,從而在管理中啓用每一個對象的權限:
rules comes with a custom ModelAdmin subclass,rules.contrib.admin.ObjectPermissionsModelAdmin, that overrides these methods to pass on the edited model instance to the authorization backends, thus enabling permissions per object in the Admin:
# books/admin.py
from django.contrib import admin from rules.contrib.admin import ObjectPermissionsModelAdmin from .models import Book class BookAdmin(ObjectPermissionsModelAdmin): pass admin.site.register(Book, BookAdmin)
Now this allows you to specify permissions like this:
>>> rules.add_perm('books', rules.always_allow) >>> rules.add_perm('books.add_book', has_author_profile) >>> rules.add_perm('books.change_book', is_book_author_or_editor) >>> rules.add_perm('books.delete_book', is_book_author)
爲了保持向後兼容性,Django將請求查看或更改權限。爲了得到最大的靈活性,規則的行爲略有不一樣:若是而且僅當視圖權限不存在規則時,規則纔會請求更改權限。
To preserve backwards compatibility, Django will ask for either view or change permission. For maximum flexibility, rules behaves subtly different: rules will ask for the change permission if and only if no rule exists for the view permission.
Similar to rules.contrib.views.autopermission requiredmixin,there is arules.contrib.rest=uframework.autopermissions viewsetmixin for viewsets in Django rest framework.不一樣之處在於,這並非從視野類型得到的許可,而是從API行動(創做、檢索等)中得到的許可,而API行動力求獲得許可。固然,它要求你使用規則中的混合物。contrib.modelswhen declaring models the API should operate on.
這是一個徹底自動化的許可證檢查的可能的模型:
Similar to rules.contrib.views.AutoPermissionRequiredMixin, there is arules.contrib.rest_framework.AutoPermissionViewSetMixin for viewsets in Django Rest Framework. The difference is that it doesn’t derive permission from the type of view but from the API action (create, retrieveetc.) that’s tried to be performed. Of course, it requires you to use the mixins from rules.contrib.modelswhen declaring models the API should operate on.
Here is a possible ModelViewSet for the Post model with fully automated CRUD permission checking:
from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from rules.contrib.rest_framework import AutoPermissionViewSetMixin from posts.models import Post class PostSerializer(ModelSerializer): class Meta: model = Post fields = "__all__" class PostViewSet(AutoPermissionViewSetMixin, ModelViewSet): queryset = Post.objects.all() serializer_class = PostSerializer
默認狀況下,modelviewset的CRUD操做映射到本機django權限類型(添加、更改、刪除和查看)。列表操做未啓用權限檢查。可是,在使用(或子類化)autopermissionviewsetmixin時,能夠徹底擴展、更改或替換預約義的映射。而後也能夠映射經過@action decorator定義的自定義API操做。有關如何正確自定義默認行爲的詳細信息,請參閱完整文檔化的源代碼。
By default, the CRUD actions of ModelViewSet are mapped to the native Django permission types (add, change, delete and view). The list action has no permission checking enabled. However, the pre-defined mappings can be extended, changed or replaced altogether when using (or subclassing)AutoPermissionViewSetMixin. Custom API actions defined via the @action decorator may then be mapped as well. See the fully documented source code for details on how to properly customize the default behaviour.
You may create as many rule sets as you need:
>>> features = rules.RuleSet()
And manipulate them by adding, removing, querying and testing rules:
>>> features.rule_exists('has_super_feature') False >>> is_special_user = rules.is_group_member('special') >>> features.add_rule('has_super_feature', is_special_user) >>> 'has_super_feature' in features True >>> features['has_super_feature'] <Predicate:is_group_member:special object at 0x10eeaa500> >>> features.test_rule('has_super_feature', adrian) True >>> features.remove_rule('has_super_feature')
Note however that custom rule sets are not available in Django templates – you need to provide integration yourself.
新上下文是做爲調用predicate.test()的結果建立的,而且僅在調用期間有效。上下文是一個簡單的dict,您可使用它來存儲任意數據(例如緩存計算值、設置標誌等),謂詞稍後能夠在鏈中使用它。在謂詞函數內部,能夠這樣使用:
A new context is created as a result of invoking Predicate.test() and is only valid for the duration of the invocation. A context is a simple dict that you can use to store arbitrary data, (eg. caching computed values, setting flags, etc.), that can be used by predicates later on in the chain. Inside a predicate function it can be used like so:
>>> @predicate ... def mypred(a, b): ... value = compute_expensive_value(a) ... mypred.context['value'] = value ... return True
Other predicates can later use stored values:
>>> @predicate ... def myotherpred(a, b): ... value = myotherpred.context.get('value') ... if value is not None: ... return do_something_with_value(value) ... else: ... return do_something_without_value()
Predicate.context provides a single args attribute that contains the arguments as given to test() at the beginning of the invocation.
在謂詞的函數體中,能夠經過其名稱引用謂詞實例自己,例如is_book_author。將bind=true做爲關鍵字參數傳遞給謂詞修飾器將容許您使用self引用謂詞,這更方便。束縛自我只是句法上的糖分。事實上,如下兩項是等效的:
In a predicate’s function body, you can refer to the predicate instance itself by its name, eg. is_book_author. Passing bind=True as a keyword argument to the predicate decorator will let you refer to the predicate with self, which is more convenient. Binding self is just syntactic sugar. As a matter of fact, the following two are equivalent:
>>> @predicate ... def is_book_author(user, book): ... if is_book_author.context.args: ... return user == book.author ... return False >>> @predicate(bind=True) ... def is_book_author(self, user, book): ... if self.context.args: ... return user == book.author ... return False
You may skip evaluation by returning None from your predicate:
>>> @predicate(bind=True) ... def is_book_author(self, user, book): ... if len(self.context.args) > 1: ... return user == book.author ... else: ... return None
Returning None signifies that the predicate need not be evaluated, thus leaving the predicate result up to that point unchanged.
能夠選擇將規則配置爲在計算規則以幫助調試謂詞時記錄調試信息。消息在調試級別發送到「rules」記錄器。如下dictconfigconfigures配置一個控制檯記錄器(若是在Django中使用規則,請將其放在項目的settings.py中):
rules can optionally be configured to log debug information as rules are evaluated to help with debugging your predicates. Messages are sent at the DEBUG level to the 'rules' logger. The following dictConfigconfigures a console logger (place this in your project’s settings.py if you’re using rules with Django):
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', }, }, 'loggers': { 'rules': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': True, }, }, }
When this logger is active each individual predicate will have a log message printed when it is evaluated.
在測試規則以前,必須用規則集註冊這些規則,爲此,必須導入包含規則定義的模塊。
對於具備多個謂詞和規則的複雜項目,在一個模塊中定義全部謂詞和規則可能並不實際。最好將它們分割到項目的任何子組件中。在Django上下文中,這些子組件多是項目的應用程序。
另外一方面,因爲從各地導入謂詞以定義規則會致使循環導入和心碎,所以最好在不一樣模塊中進一步拆分謂詞和規則。
能夠選擇將規則配置爲應用程序中的autodiscover rules.py模塊,並在啓動時導入它們。要讓規則這樣作,只需編輯已安裝的應用程序設置:
Before you can test for rules, these rules must be registered with a rule set, and for this to happen the modules containing your rule definitions must be imported.
For complex projects with several predicates and rules, it may not be practical to define all your predicates and rules inside one module. It might be best to split them among any sub-components of your project. In a Django context, these sub-components could be the apps for your project.
On the other hand, because importing predicates from all over the place in order to define rules can lead to circular imports and broken hearts, it’s best to further split predicates and rules in different modules.
rules may optionally be configured to autodiscover rules.py modules in your apps and import them at startup. To have rules do so, just edit your INSTALLED_APPS setting:
INSTALLED_APPS = ( # replace 'rules' with: 'rules.apps.AutodiscoverRulesConfig', )
Note: On Python 2, you must also add the following to the top of your rules.py file, or you’ll get import errors trying to import rules itself:
from __future__ import absolute_import
核心API能夠從根規則模塊訪問。管理和視圖的Django特定功能可從rules.contrib得到。
The core APIs are accessible from the root rules module. Django-specific functionality for the Admin and views is available from rules.contrib.
You create Predicate instances by passing in a callable:
>>> def is_book_author(user, book): ... return book.author == user ... >>> pred = Predicate(is_book_author) >>> pred <Predicate:is_book_author object at 0x10eeaa490>
You may optionally provide a different name for the predicate that is used when inspecting it:
>>> pred = Predicate(is_book_author, name='another_name') >>> pred <Predicate:another_name object at 0x10eeaa490>
Also, you may optionally provide bind=True in order to be able to access the predicate instance with self:
>>> def is_book_author(self, user, book): ... if self.context.args: ... return user == book.author ... return False ... >>> pred = Predicate(is_book_author, bind=True) >>> pred <Predicate:is_book_author object at 0x10eeaa490>
RuleSet extends Python’s built-in dict type. Therefore, you may create and use a rule set any way you’d use a dict.
Decorator that creates a predicate out of any callable:
>>> @predicate ... def is_book_author(user, book): ... return book.author == user ... >>> is_book_author <Predicate:is_book_author object at 0x10eeaa490>
Customising the predicate name:
>>> @predicate(name='another_name') ... def is_book_author(user, book): ... return book.author == user ... >>> is_book_author <Predicate:another_name object at 0x10eeaa490>
Binding self:
>>> @predicate(bind=True) ... def is_book_author(self, user, book): ... if 'user_has_special_flag' in self.context: ... return self.context['user_has_special_flag'] ... return book.author == user
django-rules is distributed under the MIT licence.
Copyright (c) 2014 Akis Kesoglou
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 「Software」), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 「AS IS」, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.