How do you change <title> of a Satchmo Store? - python

This seems like something that should be obvious, but I simply can't find it.
I created a Satchmo store using clonesatchmo.py, as indicated by the installation instructions.
I have tried to change the name of the site through the admin interface (going to Sites and changing the display name) and by editing local_setting.py, changing the line:
SITE_NAME = "Simple Satchmo"
to
SITE_NAME = "Anything Else"
By neither change impacts the actual store. Simple Satchmo remains in the title field, mocking me. So, what idiotic thing am I doing wrong?

You need to go to Admin, Store configurations and change the Store Name for your store.

Modify the tittle by web site Admin on both Shop / Store Configuration: Store Name.
and Sites / Sites: Display Name. They should be the same.
The latter name is used by some utils related to Django, like sending registration email.
Setting the line SITE_NAME has any effect only before the first running "clonesatchmo.py" or "manage.py satchmo_load_store". Note that the line is preceded by a comment
# These are used when loading the test data
This is not enough explanatory IMO. I will suggest in the development team to remove it by installation script in Satchmo 0.9.3. It will be at least better explained now.

Related

Django: DoesNotExist: SocialApp matching query does not exist

I'm trying to activate social logins in my Django web application, which comes from open source software in this GitHub repository (so I didn't write it); and am running into this well-known issue:
DoesNotExist: SocialApp matching query does not exist.
The base settings file is located here. I do not modify that file at all. Instead, I import (inherit) it at the top of my deploy.py settings file, and make overrides and customization there.
Specifically related to this issue, here are the relevant overrides and additions that I made in deploy.py to enable Google and Twitter social authentication, both of which result in the same error:
INSTALLED_APPS.remove('allauth.socialaccount.providers.persona') # Remove
INSTALLED_APPS.append('allauth.socialaccount.providers.google') # Add
INSTALLED_APPS.append('allauth.socialaccount.providers.twitter') # Add
_GOOGLE = {
'SCOPE': ['email', 'https://www.googleapis.com/auth/userinfo.profile'],
'AUTH_PARAMS': {'access_type': 'online'},
'PROVIDER_KEY': get_env("GOOGLE_PROVIDER_KEY"), # Stored in secrets.env
'PROVIDER_SECRET_KEY': get_env("GOOGLE_PROVIDER_SECRET_KEY"), # Stored in secrets.env
}
SOCIALACCOUNT_PROVIDERS['google'] = _GOOGLE # This isn't enabled in biostar.settings.base
_TWITTER = {
'SCOPE': ['email'],
'AUTH_PARAMS': {'access_type': 'online'},
'PROVIDER_KEY': get_env("TWITTER_PROVIDER_KEY"), # Stored in secrets.env
'PROVIDER_SECRET_KEY': get_env("TWITTER_PROVIDER_SECRET_KEY"), # Stored in secrets.env
}
SOCIALACCOUNT_PROVIDERS['twitter'] = _TWITTER
I show two provider examples here -- Twitter and Google -- to show the pattern of what I am doing, and to show that the issue isn't provider-specific; though let's try to focus on just Twitter to keep things simple.
Now according to this document -- which comes from a close fork of the above project -- in addition to what I implemented above (programmatically), it is necessary to also set up the same Social Accounts and the Keys/Secret-keys for them in the Social Apps section of the Django Admin panel. (Note that that fork was worked on by more-or-less the same team; so this requirement likely applies to the original upstream implementation, as well). The relevant part of that document instructs the following:
After restoring, you need to re-enter social login info.
Unfortunately, even though this information is required to be in the config
environment that initializes biostar, it also requires it
(redundantly) to be in the database as well. So go to the Django Admin panel
and click on Social Apps and then go through each app and fill in the
appropriate values.
So I went ahead and did that, too.
No matter what I try (different providers, different keys, django panel additions, no django panel additions, etc), I get the aforementioned exception, as though I'm missing a step.
Incidentally, I tried both key-pairs for Twitter (because I always forget which pair to use; so tried both Consumer Key (API Key) + Consumer Secret (API Secret) and Access Token + Access Token Secret, though it's really the former from what I read online). Just mentioning this for completeness.
What am I missing? Any ideas?
Thank you in advance! :)
EDIT-1: Here is a full paste of the exception: https://pastebin.com/0UBAfAtu
I was getting the same error again and again and solve with this ..
The reason we get this error SITE_ID = 1
When "SocialApp matching query does not exist" occurs,
this ID needs to be replaced.
SITE_ID = 1
hope for anyone else facing this issue will get help for this.
Following below steps will resolve this issue:
Go to your database table named django_site.
Look at the id number of the site mentioned as a chosen site in the Social Applications.
Now configure SITE_ID to id number in setting.py of the Django project.
I had a similar problem and as people have said, you need to know the SITE_ID!
You have to make sure that on the Django admin dashboard, you have added your social application under SOCIAL ACCOUNTS.
When you're creating the social application, make sure that have listed the right websites for "chosen sites". If you're on local development, paste your computer IP in there. There will be a new SITE_ID associated with each "Chosen site" that you add to your application. Make sure you're using the right one that's associated to your IP. Personally, after adding my IP, I then just played and incremented my SITE_ID variable until it worked.
Posting this in case someone in a similar situation in the future lands on this page.

Django Migrate Change of App Name (active project)

So... I've done a lot of research on this... there are answers, but not complete or appropriate answers. I have an in-use and in-production django "project" in which the "main" application is called "pages" ... for reasonably dumb reasons. My problem is now to add mezzanine ... which has a sub-module mezzanine.pages (seems to be required .... but I'm pretty sure I need it).
mezzanine.pages apparently conflicts with "pages" ...
Now ... my pages contains a slew of non-trivial models including one that extends user (One-to-One ref), and many references to other app's tables (fortunately only outbound, ForeignKey). It also has management/commands and about 20 migrations of it's own history.
I gather I either have to changes pages to mypages or is there another route (seemingly changing mezzanine.pages seems wrong-headed).
for reference, The project is on Django 1.8 right now, so the preferred answer includes migrations.
I've worked on this since I posted it, and the real answer is what I've synthesized from multiple sources (including other stack exchange posts).
So... Everything changed in Django before I started using it. After 1.7, the 'migrations' bit was internalized and posts including the word "South" are about how the world was before 1.7. Further, the complication in my case dealt with the issue of migrations in that the project was already active and had real data in production.
There were some posts including a GITHub chunk of code that talked about migrating tables from one App to another App. This is inherently part of the process, but several posts noted that to do this as a "migration" you needed the Migration.py to be in another App. Maybe even an App created for the purpose.
In-the-end, I decided to approach the problem by changing the label in the Application class of apps.py in the application in question. In my case, I am changing "pages" to "phpages" but the directory name of my app is still pages. This works for me because the mezzanine app's "pages" sub-App is back in the python library and not a conflict in the filesystem. If this is not your situation, you can solve it with another use of label.
So... Step-by-step, my procedure to rename pages to phpages.
Create apps.py in the pages sub-directory. In it put:
class PagesConfig(AppConfig):
name = "pages"
label = "phpages"
verbose_name = "Purple Hat Pages"
Key among these is label which is going to change things.
In __init__.py in the pages sub-directory, put default_app_config = "pages.apps.PagesConfig"
In your settings.py change the INSTALLED_APPS entry for your app to 'pages.apps.PagesConfig', ...
All of your migrations need to be edited in this step. In the dependencies list, you'll need to change 'pages' to 'phpages'. In the ForeignKeys you'll need to also change 'pages.Something' to 'phpages.Something' for every something in every migration file. Find these under pages/mitrations/nnnn_*.py
If you refer to foreign keys in other modules by from pages.models import Something and then use ForeignKey(Something), you're good for this stop. If you use ForeignKey('pages.Something') then you need to change those references to ForeignKey('phpages.Something'). I would assume other like-references are the same.
For the next 4 steps (7, 8, 9 and 10), I built pagestophpages.sql and added it to the pages sub-directory. It's not a standard django thing, but each test copy and each production copy of the database was going to need the same set of steps.
UPDATE django_contecnt_type SET app_label='phpages' WHERE app_label='pages';
UPDATE django_migrations SET app='phpages' WHERE app='pages';
Now... in your database (my is PostgreSQL) there will be a bunch of tables that start with "pages". You need to list all of these. In PostgreSQL, in addition to tables, there will be sequences for each AutoField. For each table construct ALTER TABLE pages_something RENAME TO phpages_something; For each sequence ALTER SEQUENCE pages_something_id_seq RENAME TO phpages_something_id_seq;
You should probably backup the database. You may need to try this a few times. Run your SQL script through your database shell. Note that all other changes can be propagated by source code control (git, svn, etc). This last step must be run on each and every database.
Obviously, you need to change pages and phpages to your stuff. You may have more than one table with one auto field and it may not be named something.
Another thing of note, in terms of process, is that this is probably a hard point in your development where everything needs be in sync. Given that we're playing with editing migrations and changing names, you need a hard stop in development so that everything that's going to be changed (dev box, test box, staging box, production box ... and all of their databases) is at the same revision and schema. YMMV.
This is also solving the problem by using the label field of class Application. I choose this method in deference to changing the directory name because it involved fewer changes. I chose not to change the name field because that did not work for me. YMMV.
I must say that I'm a little disappointed that myapp/pages conflicts with mezzanine.pages. It looks like some of the reasons are due to the pages slug being used in the database table name (and off top of my head, I don't see a good solution there). What I don't see that would make sense is the equivalent to "from mezzanine import pages as mpages" or somesuch. The ability to alias imported apps (not talking about apps in my own file tree). I think this might be possible if I sucked in the app into my own file tree --- but this doesn't seem to be a sanctioned act, either.

Configuring multi-tenancy

In a local dev env, I'm currently attempting to hack my way to multi-tenancy using Mezzanine:
Mezzanine makes use of Django’s sites app to support multiple sites in a single project. This functionality is always “turned on” in Mezzanine:
That's pretty much as far as an entry-level tut for multi-tenancy on mezzanine gets. Great, so I go to the admin site, and add a site:
Domain name-----|----Display name
127.0.0.1:8000----|----English Site
127.0.0.1:8000/es|----Spanish Site
Now, I am stuck. I have fiddled around with url.py, but figured that's not where to start, considering I need to know something to map the url to. Views? Lost.
Any ideas?
(Included translation is not an option given the web service will never translate as good as a human.)
Multitenancy in mezzanine is done via domain names. You will need to run http://dev.site and http://esdev.site or similar in development (add the entries to your hosts file and make sure they match the listings in the sites part of admin).
In production you'll also want to use two different domains too.
For example, my personal site http://dpn.name/ and my business site http://behest.com.au/ are both running off the same mezzanine install.
Later on when you have the right setup, you'll be able to add new posts and pages to each specific site by either logging into the admin via each domain name, or changing the currently active site in the admin (the drop down is in the top right if you have multiple sites set up)
Hope that helps, please let me know if you need more info.

Django admin site: how to create a single page for global settings?

I would like to create a single page in the admin site of django where I can change some global variables of the website (title of the website, items in the navigation menu, etc). At the moment I have them coded as context processors but I would like to make them editable. Something similar to what happens in WordPress.
Is this possible?
I can store the data in the databse, but can I have a link in the admin site that goes straight to the first document record and doesnt allow the creation of multiple records (they wouldnt make sense)
Instead of creating a model in the database, would it be possible to change some context_processor from the admin site (I think this would be best)
django-preferences does exactly what you are looking for. The implementation is a bit hacky (particularly the setting of __module__ on the model class to trick Django into thinking it was loaded from a different app), but it works.
This sounds like what the sites framework is intended to help with.
http://docs.djangoproject.com/en/stable/ref/contrib/sites/
"It’s a hook for associating objects and functionality to particular Web sites, and it’s a holding place for the domain names and “verbose” names of your Django-powered sites."
The docs make it sound like it's only good for multiple sites, but it's a great place to put stuff in a single-site-per-django model too.
There's an app called django-values that allows you storing of specific settings in the database.

How to make some Django settings accessible by staff?

In Django, settings are stored in a file, settings.py. This file is part of the code, and goes into the repository. It is only the developers who deal with this file. The admin deals with the models, the data in the database. This is the data that the non-development staff edits, and the site visitors see rendered in templates.
The thing is, our site, and many others, have lots of settings options that should be edited by non-developer staff. We're talking about stand-alone site-wide constants that really have no place in the database. Putting them in the database will result in numerous pointless queries. Caching could alleviate that, but that seems unnecessarily complex to handle what can be done with a single line in the settings.py file.
I did notice this dbsettings app, but it is old and unmaintained. I also noticed that the django e-commerce app, Satchmo, includes a use-case specific fork of this dbsettings app. We could build something similar into our site, an app that stores some settings as key/value pairs in a single database table, but it just really seems like the wrong approach. Why put something in the DB that doesn't belong there just to make it more easily editable by non-developers?
We have a list of site-wide settings on our Django site that we want to be editable by non-developer administrators. What is the best way of going about this?
Something like dbsettings (as you mentioned) seems like the way to go. From the reasons for existence for that project:
Not all settings belong in
settings.py, as it has some
particular limitations:
Settings are project-wide. This not only requires apps to clutter up
settings.py, but also increases the chances of naming
conflicts.
Settings are constant throughout an instance of Django. They cannot be
changed without restarting the application.
Settings require a programmer in order to be changed. This is true even
if the setting has no functional impact on anything else.
If dbsettings doesn't work for you, then implement your own, or fork it. It doesn't seem like it'd be too arduous.
I'm actually a big fan of dbsettings, and keep meaning to publish my fork that patches it to work with Django 1.1 (not actually a big change). Looks like someone has updated it already.
However, you're probably right that this is overkill for what you need. One thing I've done before is to add a line to the end of settings.py that imports and parses a YAML file. YAML is a simple markup language, which at its most basic is just KEY: VALUE ...
CONSTANT1: MyValue
CONSTANT2: Anothervalue
If you put this somewhere editors can access it, then at the end of settings.py you just do:
import yaml
try:
globals().update(yaml.load(open('/path/to/my/yaml/file.yml')))
except:
pass
You'll need the Python YAML library to parse the YML file.
The downside to this approach is that you'll need to restart Apache to get it to pick up the changes.
Edited to add It wouldn't be particularly difficult to build a front end which could edit this file, and provide a button which runs a script to restart Apache.
If you must avoid server restarts then a logical place for the settings is the database as Dominic and Daniel said, but you'll need to invalidate cached settings object every time it is updated.
Looks like it's possible to re-set values in the cache with Django's low level cache API. All you want should be achievable with these calls:
cache.set('settings', local_settings)
cache.add('settings', local_settings)
local_settings = cache.get('settings')
cache.delete('settings')
How about putting a sitesettings.py (or whatever) somewhere that your admins can access, then in settings.py do
from sitesettings import *
That seems good and simple, but I may have misunderstood or oversimplified your problem :)
models.py
class Setting(models.Model):
"""Global settings for app"""
name = models.CharField(max_length=100, null=False, blank=False)
value = models.CharField(max_length=100, null=False, blank=False)
def __str__(self):
return self.name
admin.py
from YOUR_APP.models import Setting
class SettingAdmin(admin.ModelAdmin):
list_display = (
'name',
'value',
)
admin.site.register(Setting, SettingAdmin)
extras.py
#register.filter
def get_setting(name):
setting = Setting.objects.get(name=name)
return setting.value
template.html
{% if 'setting_name'|get_setting == 'true' %}
Display your Feature
{% endif %}
Django Packages has a page that lists packages that provide such functionality - most query the database and then use caching to minimize hits on the DB.
I found Django Dynamic Preferences to be of particular interest due to the fine-grained control it gives you over the configuration.

Categories