Package: django-tos
django-tosThis project gives the admin the ability to reset terms of agreement with the end users. It tracks when TOS are changed and when users agree to the new TOS.SummaryKeeps track of when TOS is changedUsers need to be informed and agree/re-agree when they login (custom login is provided)Just two models (TOS and user agreement)Terms Of Service Installationpip installdjango-tosAddtosto yourINSTALLED_APPSsetting.Sync your database withpython manage.py migrateConfigurationOptionsThere are two ways to configuredjango-tos- either enable the TOS check when users sign in, or use middleware to enable the TOS check on everyGETrequest.If you cannot override your login view (for instance, if you’re usingdjango-allauth) you should use the second option.Option 1: TOS Check On Sign InIn your root urlconf fileurls.pyadd:fromtos.viewsimportlogin# terms of service linksurlpatterns+=patterns('',url(r'^login/$',login,{},'auth_login',),url(r'^terms-of-service/',include('tos.urls')),)Option 2: Middleware CheckThis option uses theincrmethods for the configured Django cache. If you are usingdjango-tosin a complex or parallel environment, be sure to use a cache backend that supports atomic increment operations. For more information, see the notes at the end ofthis section of the Django documentation.Also, to ensure that warming the cache with users who can skip the agreement check works properly, you will need to includetosbefore your app (myappin the example) in yourINSTALLED_APPSsetting:INSTALLED_APPS=(...'tos',...'myapp',# Example app name...)AdvantagesCan optionally use a separate cache for TOS agreements (necessary if your default cache does not support atomic increment operations)Allow some of your users to skip the TOS check (eg: developers, staff, admin, superusers, employees)Uses signals to invalidate cached agreementsSkips the agreement check when the user is anonymous or not signed inSkips the agreement check when the request is AJAXSkips the agreement check when the request isn’t aGETrequest (to avoid getting in the way of data mutations)DisadvantagesRequires a cache key for each user who is signed inRequires an additional cache key for each staff userMay leave keys in the cache when the activeTermsOfServicechangesEfficiencyBest case for staff users: 2 cache hitsBest case for non-staff users: 1 cache miss, 2 cache hitsWorst case: 1 cache hit, 2 cache misses, 1 database query, 1 cache set (this should only happen when the user signs in)Option 2 ConfigurationIn your root urlconf fileurls.pyonly add the terms-of-service URLs:# terms of service linksurlpatterns+=patterns('',url(r'^terms-of-service/',include('tos.urls')),)Optional: Since the cache used by TOS will be overwhelmingly read-heavy, you can use a separate cache specifically for TOS. To do so, create a new cache in your project’ssettings.py:CACHES={...# The cache specifically for django-tos'tos':{# Can use any name here'BACKEND':...,'LOCATION':...,'NAME':'tos-cache',# Can use any name here},}and configuredjango-tosto use the new cache:TOS_CACHE_NAME='tos'# Must match the key name in in CACHESthis setting defaults to thedefaultcache.Then in your project’ssettings.pyadd the middleware toMIDDLEWARE_CLASSES:MIDDLEWARE_CLASSES=(...# Terms of service checks'tos.middleware.UserAgreementMiddleware',)Optional: To allow users to skip the TOS check, you will need to set corresponding cache keys for them in the TOS cache. The cache key for each user will need to be prefixed withdjango:tos:skip_tos_check:, and have the user ID appended to it.Here is an example app configuration that allows staff users and superusers to skip the TOS agreement check:fromdjango.appsimportAppConfig,appsfromdjango.confimportsettingsfromdjango.contrib.authimportget_user_modelfromdjango.core.cacheimportcachesfromdjango.db.modelsimportQfromdjango.db.models.signalsimportpost_save,pre_savefromdjango.dispatchimportreceiverclassMyAppConfig(AppConfig):name='myapp'defready(self):if'tos'insettings.INSTALLED_APPS:cache=caches[getattr(settings,'TOS_CACHE_NAME','default')]tos_app=apps.get_app_config('tos')TermsOfService=tos_app.get_model('TermsOfService')@receiver(post_save,sender=get_user_model(),dispatch_uid='set_staff_in_cache_for_tos')defset_staff_in_cache_for_tos(user,instance,**kwargs):ifkwargs.get('raw',False):return# Get the cache prefixkey_version=cache.get('django:tos:key_version')# If the user is staff allow them to skip the TOS agreement checkifinstance.is_stafforinstance.is_superuser:cache.set('django:tos:skip_tos_check:{}'.format(instance.id),version=key_version)# But if they aren't make sure we invalidate them from the cacheelifcache.get('django:tos:skip_tos_check:{}'.format(instance.id),False):cache.delete('django:tos:skip_tos_check:{}'.format(instance.id),version=key_version)@receiver(post_save,sender=TermsOfService,dispatch_uid='add_staff_users_to_tos_cache')defadd_staff_users_to_tos_cache(*args,**kwargs):ifkwargs.get('raw',False):return# Get the cache prefixkey_version=cache.get('django:tos:key_version')# Efficiently cache all of the users who are allowed to skip the TOS# agreement checkcache.set_many({'django:tos:skip_tos_check:{}'.format(staff_user.id):Trueforstaff_useringet_user_model().objects.filter(Q(is_staff=True)|Q(is_superuser=True))},version=key_version)# Immediately add staff users to the cacheadd_staff_users_to_tos_cache()django-tos-i18ndjango-tos internationalization using django-modeltranslation.Terms Of Service i18n InstallationAssuming you have correctly installed django-tos in your app you only need to
add following apps toINSTALLED_APPS:INSTALLED_APPS+=('modeltranslation','tos_i18n')and also you should also define your languages in DjangoLANGUAGESvariable, e.g.:LANGUAGES=(('pl','Polski'),('en','English'),)Please note that adding those toINSTALLED_APPSchangesDjango models.
Concretely it adds for every registeredfieldthat should translated,
additional fields with namefield_<lang_code>, e.g. for given model:classMyModel(models.Model):name=models.CharField(max_length=10)There will be generated fields:name,name_en,name_pl.You should probably migrate your database, and if you’re using Django < 1.7 using South is recommended. These migrations should be kept in your local project.How to migrate tos with SouthHere is some step-by-step example how to convert your legacy django-tos
instalation synced using syncdb into a translated django-tos-i18n with South
migrations.Inform South that you want to store migrations in custom place by putting
this in your Django settings file:SOUTH_MIGRATION_MODULES={'tos':'YOUR_APP.migrations.tos',}Add required directory (package):mkdir-pYOUR_APP/migrations/tostouchYOUR_APP/migrations/tos/__init__.pyCreate initial migration (referring to the database state as it is now):pythonmanage.pyschemamigration--initialtosFake migration (because the changes are already in the database):pythonmanage.pymigratetos--fakeInstall tos_i18n (and modeltranslation) toINSTALLED_APPS:INSTALLED_APPS+=('modeltranslation','tos_i18n',)Make sure that the DjangoLANGUAGESsetting is properly configured.Migrate what changed:$pythonmanage.pyschemamigration--autotos$pythonmigratetosThat’s it. You are now running tos in i18n mode with the languages you declared
inLANGUAGESsetting. This will also make all required adjustments in the
Django admin.For more info on how translation works in details please refer to thedjango-modeltranslation documentation.