Should I remove 'django.contrib.comments' from my installed apps when I modify it by subclassing? - django

I'm customizing django comments.
According to the docs you'll need to add your customized app to INSTALLED_APPS in settings.py, and set COMMENTS_APP to your app name.
INSTALLED_APPS = [
...
'my_comment_app',
...
]
COMMENTS_APP = 'my_comment_app'
Should I also remove 'django.contrib.comments' from INSTALLED_APPS?

If you are only extending contrib.comments not replacing it, you shouldn't remove it from installed apps since, for example, most of the templatetags you need are in that application.
In order for Django to find the templates, templatetags and so on app must be in the installed apps.

Related

Wagtail and allauth - allauth is inheriting site name from django not wagtail

I am using allauth with wagtail. I have name my site 'mysite' in the wagtail admin, but when sign up emails refer to 'example.com'
My settings.py has apps in the following order
[ ...
'django.contrib.auth',
'django.contrib.sites',
"allauth",
"allauth.account",
"allauth.socialaccount",
"allauth.account",
"allauth.socialaccount",
'wagtail.contrib.forms',
'wagtail.contrib.redirects',
'wagtail.embeds',
'wagtail.sites',
'wagtail.users',
'wagtail.snippets',
'wagtail.documents',
'wagtail.images',
'wagtail.search',
'wagtail.admin',
'wagtail.core',
]
It sounds as though this might be related to the conflict between django and wagtail described here https://github.com/wagtail/wagtail/issues/2840. However it looks as though that issue has been closed and I am using recent version (Django==3.2.11, django-allauth==0.47.0, wagtail==2.15.1)
This is the expected behaviour - django-allauth is a Django package, not a Wagtail-specific one, and always uses Django's site model even when Wagtail is active. To update the site name, log in to the Django admin backend (as distinct from the Wagtail one - this can be found at http://localhost:8000/django-admin/ if you set up your project with the wagtail start command) and go to the Sites item.
The issue being fixed in https://github.com/wagtail/wagtail/issues/2840 was that Wagtail and django-allauth could not coexist at all, due to both of them trying to set a conflicting request.site variable.

Impossible to use django-allauth when there is already an `account` app?

My Django application already has an app called account. Does it mean that it is ABSOLUTELY impossible to use django all-auth because of the name conflict? Due to the existing data, the app account cannot be renamed.
settings.py:
INSTALLED_APPS = [
...
'account',
...
# For allauth:
'django.contrib.sites',
'allauth',
'allauth.account', # Name conflict
...
If so, is there a good alternative?
2-14
Per solarissmoke's suggestion. Where should I put the new app and what is it name?
Is it something like this (Of course, it is wrong)?
my_project/account/apps.py:
import allauth.account
from django.apps import AppConfig
class AccountConfig(AppConfig):
name = 'account'
class AllAuthAccountConfig(allauth.account):
name = 'allauth.account'
label = 'allauth_account' # Change this
verbose_name = 'aullauth_account'
This is a known problem with django-allauth.
You can work around it by changing your own app to use a different app label. In your app's AppConfig:
class AccountConfig(AppConfig):
name = 'my_project.apps.account'
label = 'my_project_account' # Change this
verbose_name = 'account'
And refer to this app config in your INSTALLED_APPS, e.g.,
INSTALLED_APPS = [
...
'account.apps.AccountConfig',
...
'allauth',
'allauth.account',
...
Which should now work because the app labels are unique. Note that the only issue with this is that database tables names for your account app will have to change so as not to conflict with the allauth app - this will require some data migrations (if on an established project) or creation of fresh migrations (if on a project where you can afford to clobber the database).
You can also do this with the allauth.account app if that's easier - just create a new app config anywhere in your project, e.g.,
my_project/allauth_apps/apps.py (make sure to also create __init__.py in this new directory):
class AllAuthAccountConfig(allauth.account):
name = 'allauth.account'
label = 'allauth_account' # Change this
verbose_name = 'aullauth_account'
And then in your INSTALLED_APPS replace account with my_project.allauth_apps.apps.AllAuthAccountConfig. As above, this changes the database table names.
you need to fork the git on your own and change the label
fork the source code from https://github.com/pennersr/django-allauth/
add unique label such as allauthaccount to app in django-allauth/allauth/account/apps.py on your own forked git
commit
add following line to your requirements.txt -e git+https://github.com/andylee0213/django-allauth#egg=django_allauth
do "pip install -r requirements.txt and pip freeze > requirements.txt" and check github link is still in requirements.txt
but my suggestion is, instead of not receiving updates and going through all this pain, just use other auth libraries. There are many other libraries that does not depend on all auth. check
https://medium.com/codex/django-allauth-vs-dj-rest-auth-vs-python-social-auth-vs-drf-social-oauth2-ef7d50f92d16

"polls.apps.PollsConfig" and "polls" in `INSTALLED APPS'

To tell Django which apps are installed, the official documentation introduces
The advantage 'polls.apps.PollsConfig' over 'polls'
setting.py
INSTALLED_APPS = [
#my APPs
"polls.apps.PollsConfig",
]
This explicitly refer to the installed app in app.py
from django.apps import AppConfig
class LearningLogsConfig(AppConfig):
name = 'learning_logs'
However, in some books, it tell it in a shortcut
setting.py
INSTALLED_APPS = [
#my APPs
"polls",
]
How Django access 'polls' in this situation?
Django can use either option. The version with the AppConfig lets you point Django specifically to an application configuration class which lets you specify some additional config for the app.
If you just want the app as-is, refer to it by its name alone. Use the AppConfig variant only when you are supplying an AppConfig class to configure something about the application.
In the manage.py location Django will check with the string you have given in installed apps list.
Each string should be a dotted Python path to:
an application configuration class (preferred), or
a package containing an application.

DjangoCMS 3 Filter Available Plugins

In the DjangoCMS3 documentation it says you can configure DjangoCMS behavior using CMS_PLACEHOLDER_CONF in your settings. For instance:
CMS_PLACEHOLDER_CONF = {
'right-column': {
'plugins': ['TextPlugin', 'PicturePlugin'],
...
This would make TextPlugin and PicturePlugin to be the only two plugins available inside any placeholder called "right-column".
It works, but what if I want this restriction to apply to ALL placeholders??
Thanks!
Remove plugins you don't need from INSTALLED_APPS.
Alternatively, in an app after all plugin apps in INSTALLED_APPS in either cms_plugins.py or models.py you can use cms.plugin_pool.plugin_pool.unregister_plugin to remove them from the pool:
from cms.plugin_pool import plugin_pool
from unwanted_plugin_app.cms_plugins import UnwantedPlugin
plugin_pool.unregister_plugin(UnwantedPlugin)

Override default Django translations

I have a template with this:
{% trans "Log out" %}
This is translated automatically by Django to Spanish as Terminar sesión. However I would like to translate it as Cerrar sesión.
I have tried to add this literal to the .po file, however I get an error saying this literal is duplicated when I compile the messages.
Is there a way to change/override default Django translations?
Thanks.
This is what worked for me:
create a file in your app folder which will hold django messages for which translations need to be overridden, e.g. django_standard_messages.py
in django lib folder or in django.po files find the message (string) that needs to be overridden, e.g. django.forms/fields.py has message _(u"This field is required.") which we want to translate to german differently
in django_standard_messages.py add all such messages like this:
# coding: utf-8
_ = lambda s: s
django_standard_messages_to_override = [
_("This field is required."),
...
]
Translate the file (makemessages, compilemessages) - makemessages will add added django standard messages in your application .po file, find them and translate, run compilemessages to update .mo file
tryout
The logic behind: (I think ;) ) - when ugettext function searches translation for one message (string), there are several .po/.mo files that needs to be searched through. The first match is used. So, if our local app .po/.mo is first in that order, our translations will override all other (e.g. django default).
Alternative
When you need to translate all or most of django default messages, the other possibility (which I didn't tried) is to copy default django .po file in our locale or some other special folder, and fix translations and register the folder (if new) in LOCALE_PATHS django settings file as first entry in the list.
The logic behind: is the very similar as noted in previous section.
Based on Robert Lujo answer, his alternative is totally working. And IMO simpler (keep the overriden locales in a special .po file only). Here are the steps:
Add an extra path to the LOCALE_PATHS Django settings.
LOCALE_PATHS = (
# the default one, where the makemessages command will generate the files
os.path.join(BASE_DIR, 'myproject', 'locale'),
# our new, extended locale dir
os.path.join(BASE_DIR, 'myproject', 'locale_extra'),
)
find the original Django (or 3rd party) string to be translated
ex.: "recent actions" for the Django admin 'recent actions' block
Add the new .po file "myproject/locale_extra/en/LC_MESSAGES/django.po" with the alternative translation :
msgid "Recent actions"
msgstr "Last actions"
Compile your messages as usual
The easiest way is to collect the .po file found in the django.contrib.admin locale folder and re-compiling it (you can use POEdit for doing so).
You could also override the django.contrib.admin templates by putting them in your projects templates folder (for example: yourproject/templates/admin/change_form.html) then running makemessages from the project root (although this is no longer supported for django 1.4 alpha if i'm correct)
edit: Robert Lujo's answer is the clean method
This is another solution we deployed. It involved monkey patching the _add_installed_apps_translations method of the DjangoTranslation class to prioritize the translations of the project apps over the translations of the Django apps.
# patches.py
from __future__ import absolute_import, unicode_literals
import os
from django.apps import apps
from django.core.exceptions import AppRegistryNotReady
from django.utils.translation.trans_real import DjangoTranslation
def patchDjangoTranslation():
"""
Patch Django to prioritize the project's app translations over
its own. Fixes GitLab issue #734 for Django 1.11.
Might needs to be updated for future Django versions.
"""
def _add_installed_apps_translations_new(self):
"""Merges translations from each installed app."""
try:
# Django apps
app_configs = [
app for app in apps.get_app_configs() if app.name.startswith('django.')
]
# Non Django apps
app_configs = [
app for app in apps.get_app_configs() if not app.name.startswith('django.')
]
app_configs = reversed(app_configs)
except AppRegistryNotReady:
raise AppRegistryNotReady(
"The translation infrastructure cannot be initialized before the "
"apps registry is ready. Check that you don't make non-lazy "
"gettext calls at import time.")
for app_config in app_configs:
localedir = os.path.join(app_config.path, 'locale')
if os.path.exists(localedir):
translation = self._new_gnu_trans(localedir)
self.merge(translation)
DjangoTranslation._add_installed_apps_translations = _add_installed_apps_translations_new
Then in the .ready() method of your main app, call patchDjangoTranslation:
from .patches import patchDjangoTranslation
class CommonApp(MayanAppConfig):
app_namespace = 'common'
app_url = ''
has_rest_api = True
has_tests = True
name = 'mayan.apps.common'
verbose_name = _('Common')
def ready(self):
super(CommonApp, self).ready()
patchDjangoTranslation() # Apply patch
The main change are these lines:
# Django apps
app_configs = [
app for app in apps.get_app_configs() if app.name.startswith('django.')
]
# Non Django apps
app_configs = [
app for app in apps.get_app_configs() if not app.name.startswith('django.')
]
app_configs = reversed(app_configs)
The original are:
app_configs = reversed(list(apps.get_app_configs()))
Instead of interpreting the translations of the apps in the order they appear in the INSTALLED_APPS setting, this block outputs the list of apps placing the project apps before the Django apps. Since this only happens when determining the translation to use, it doesn't affect any other part of the code and no other changes are necessary.
It works on Django version 1.11 up to 2.2.