How to implement settings in admin? - django

I have Django project with my own app. This app has only two models. I need configure some options specific for this app, but in default Django admin panel.
I was thinking to create a model for example: SettingsApp and create one entry with my settings, but in admin panel, user can be add other entries or delete existing entry and app will not work. How to do it?

You should take a look at:
https://github.com/jqb/django-settings
and check if it fits well for you.

This work for my settings model:
class SettingsAdmin(admin.ModelAdmin):
def has_add_permission(self, request):
return False
def has_remove_permission(self, request):
return False

I recommend you to take a look at application django-livesettings from here. As said in documentation:
Django-Livesettings is a project split from the Satchmo Project. It
provides the ability to configure settings via an admin interface,
rather than by editing settings.py. In addition, livesettings allows
you to set sane defaults so that your site can be perfectly functional
without any changes. Livesettings uses caching to make sure this has
minimal impact on your site’s performance.
Finally, if you wish to lock down your site and disable the settings,
you can export your livesettings and store them in your settings.py.
This allows you have flexibility in deciding how various users
interact with your app.
Livesettings supports several types of input choices:
Boolean
Decimal
Duration
Float
Integer
Positive Integer
String
Long string
Multiple strings
Long multiple strings
Module values
Password
Livesettings has been used for many years in the satchmo project and
is considered stable and production ready.

Related

How to create a Django database backup?

I run multiple (more or less) identical Django (1.11) deployments running on the exact same schema, but different settings (I make my own Settings models). Values in these Settings models, of which there are plenty, are different for each deployment, so these sites can appear differently depending on the settings, for example.
A business requirement came up that requires me to regularly export these Settings models (DisplaySettings, CurrencySettings, etc.) from one stack, and import them into another stack. I know dumpdata and loaddata offer basic functionality in the form of JSON files, but I also need these extra functionalities from the business side:
The admin must be able to select which settings to export, including ForeignKey and ManyToManyField relations that may be in these settings.
When importing that file, the admin must be able to choose which settings in the file to import, and how (update the existing settings model, or create a new one).
The same exported file can be re-imported into the same stack to create duplicate copies of these settings.
Here are the solutions I have tried so far:
dumpdata/loaddata: Does not need the "choose which settings to import/export" requirement.
django-import-export: only supports exporting of tabular structures, i.e. foreign keys cannot be exported as part of a settings record.
django-easydump: completely unrelated package that uploads the dump to s3. Can specify which models to include, but not the attributes in each model to include.
Writing custom nested ModelSerializers in djangorestframework: doable but tedious. Requires custom front-end to handle the first requirement.
My question is: is there already a built-in way to do perform imports/exports as described, or if not, are there any qualifying third-party packages, not listed above, that I have obviously missed?
There's nothing built in that will handle all of your requirements.
If the schema is the same across all your deployments the easiest thing to do would be to set up drf endpoints for each model. Unless I'm missing something they don't need to be nested.
def import_currency_settings(new=False, remove_fields=[]):
endpoint = default_domain + '/currency_settings/'
settings = requests.get(endpoint, auth=(api_user, api_pass)).json()
for setting in settings:
for field in remove_fields:
setting.pop(field, None)
if new:
CurrencySettings.objects.create(**setting)
else:
updated = setting
updated.pop('id', None)
CurrencySettings.update_or_create(
id=setting['id'],
fields=updated
)
import_currency_settings(new=True, remove_fields=['vat'])

One Django Project, Multiple Settings.py

Recently I am to develop a CRM system with an e-commerce module. Since customers only log into the e-commerce website (log in with Email), staff only log into CRM,
I want to separate these two authentication model. Is it a good idea to have two sets of settings.py, one using staff as AUTH_USER_MODEL, the other one using customer as AUTH_USER_MODEL? (Maybe separate urls.py as well)
I'm going to run two different settings of app under two sub path or two domain, is this going to cause any issue? (Like concurrency issue ?)
you dont need to set two AUTH_USER_MODEL = 'myapp.MyUser' 's or two settings for this purpose which probabyly would work but this is not the level this logic belongs to. (settings is already in deployment level e.g. running multiple websites on the same codebase and same databse etc etc...)
what I would recommend is something simple:
# settings.py
AUTH_USER_MODEL = 'yourapp.CustomUser'
# yourapp's models.lpy
from django.contrib.auth.models import User
class CustomUser(models.Model):
user = models.OneToOneField(User, related_name="customuser")
crm_staff = models.Boolean(default=False)
# ...
and depending on crm_staff, the user is either crm-user or just an external user. I set the default value of crm_staff to False, so that you have to give it explicitly everytime a new user comes in, but only if user is a crm staff, then you need to set the field to True
keep it as simple as possible, you say thanks to yourself for this later..

Where is recommended spot for storing admin customizations for Django contrib apps?

I want to add Django Sessions to my Django Admin, and I am following an SO post about this, but it is unclear where I store this code. Do I put it in an admin.py file? Under what directory?
In short, it doesn't matter. You can put the code into any of your apps' admin.py files. However, in situations like these I tend to use a generic app in my project, usually named something like utils, that exists for the sole purpose of housing code that doesn't belong to one specific app or could be used by multiple apps.
If you want to be more specific, you can create a sessions app in your project specifically devoted to this code and any other code related to session management for your project, or perhaps an existing app that is somewhat related. For example, I put customizations to the User admin in my accounts app that holds the UserProfile model.

How to handle project or app specific settings in django?

How can one store, retrieve and allow the user to change the settings of a project or an app? A constant in settings.py is not good enough, as I want some users to be able to change the value of the setting. A way to present these in the admin interface would be optimal.
If it's via an admin interface then using the database sounds like a sure bet. Check out this similar looking question on StackOverflow.

How to alter django settings based on current request?

I'm running multiple sites from a single django instance, and expect the framework to eventually serve several hundred sites from one or several installations.
I need to patch some django settings based on the current request. I've written some middleware to monkey patch the settings, but I need these settings to be patched before the middleware gets invoked because other apps aren't taking the monkey-patched changes (i.e. apps get run then middleware gets run so the apps don't use the monkey-patched settings).
I should also add this is mainly for the benefit of third-party apps that I haven't written, so I don't want to go round adding decorators or anything like that because that would mess up my upgrade path.
So:
How can I get access to the current request in an app's init.py file?
Will an app's init.py get called once per request or only once? If it's only once, how else could I do this so I can manipulate the settings once per request?
Is it safe to do this kind of monkey patching? I know it makes code a bit more opaque, but I don't want to use different wsgi files per site because I want to allow users to edit some of these settings and have my monkey patching come from the database.
Is there a better solution that would allow certain settings to be stored in the database?
This module - django-tupperware does what you are asking about: https://bitbucket.org/jiaaro/django-tupperware/
Give it a try.
Never ever ever change settings on the fly. You cannot predict how the application may one day be deployed, and in most of them the project will fail in.. interesting ways.
If you really want to have hundreds of sites which will be dynamically reconfigured all the time, you might try to Djangos django/conf/__init__.py which is used to supply the settings to the rest of the framework. You might be able to alter it in a way it depends on the request and it's Host field. Or you'll get many interesting failures at the very least.
My solution to this problem is to give each request, ALL the settings and update them on the fly with a middleware, how do i do this?
Is rather simple:
This is the middleware that does it all
from django.conf import settings
class DumpObject: pass
class Settings(object):
def process_request(self,request):
request.settings = DumpObject()
for setting in dir(settings):
if not setting.startswith('__'):
setattr(request.settings, setting, getattr(settings,setting))
The DumpObject is just there so i can use the object.property notation, it could have been a dictionary, but i wanted to keep some similarity in the syntax.
This assumes that none of your settings name starts with __ which is a fair assumption.
So if i want to override a particular setting, i don't keep a settings file i do it in this middleware. like this:
class Settings(object):
def process_request(self,request):
request.settings = DumpObject()
for setting in dir(settings):
if not setting.startswith('__'):
setattr(request.settings, setting, getattr(settings,setting))
if 'mydomain' in str(request.host): #this is thanks to django-hosts project
request.settings.GOOGLE_ANALYTICS_ID = '89298393-238'
Of course this doesnt take into account the problem of accessing the settings the old way
from django.conf import settings
settings.GOOGLE_ANALYTICS_ID = 'the value in settings.py'
But it really doesn't matter because you will probably only want to change the settings on the context of having a request object, available.