Open davideghz opened 7 years ago
Hi, and thanks for your question.
First things first:
markdownx
added to the INSTALLED_APPS
in your settings file?context_processors
need to include these two processors as well (they should be there by default, unless you haven't auto-generated your settings.py
file):
django.template.context_processors.media
django.template.context_processors.static
settings.py
, I take it you don't mean that it is the whole thing, right?Hi! Thanks for your prompt answer: 1) I'm on 1.11 2) yes it added to INSTALLED_APPS: is there a specific position I have to place it? I currently have:
INSTALLED_APPS = [
'dal',
'dal_select2',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'markdownx',
'frontend',
]
being frontend my main app.
3) I didn't have those 2 context_processors, but event after addition of them and server restart, nothing happen.
4) right :) the whole thing is as follow:
"""
Django settings for mysoundlist project.
Generated by 'django-admin startproject' using Django 1.11.2.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""
import os
from django.utils.translation import ugettext_lazy as _
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '...'
ALLOWED_HOSTS = ['xyz.herokuapp.com', 'localhost', '127.0.0.1']
# Application definition
INSTALLED_APPS = [
'dal',
'dal_select2',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'markdownx',
'frontend',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'frontend.custom_context.track_seen_today',
'frontend.custom_context.track_seen_always',
'frontend.custom_context.user_avatar',
'django.template.context_processors.media',
'django.template.context_processors.static',
],
},
},
]
ROOT_URLCONF = 'xyz.urls'
WSGI_APPLICATION = 'xyz.wsgi.application'
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'CET'
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = [
('it', _('Italian')),
('en', _('English')),
]
LOCALE_PATHS = [
os.path.join(BASE_DIR, 'locale')
]
# REGISTRATION STUFF
LOGIN_REDIRECT_URL = '/profile/'
# MEDIA STUFF
MEDIA_URL = 'images/'
MEDIA_ROOT = os.path.join(BASE_DIR, "")
# FORUM STUFF
MARKDOWNX_EDITOR_RESIZABLE = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')
STATIC_URL = '/static/'
# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (
os.path.join(PROJECT_ROOT, 'static'),
)
# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
# Loading test/prod settings based on ENV settings
ENV = os.environ.get('ENV')
if ENV == 'prod':
try:
from .production_settings import *
except ImportError:
pass
else:
from .local_settings import *
Thank heavens you didn't include your secret_key
and database password. It's the first thing I check every time people post the entire thing.
You seem to be doing everything right as far as I can see; and no, the order of inclusion in INSTALLED_APPS
is not important.
So, before I go into the details of how you're trying to render stuff, would you mind just renaming widget2.html
file to widget.html
? The reason I'm asking you to do this is that I think there was an issue a while back with that we addressed (don't remember the exact details), and I'm not sure if we have updated the PyPi repository afterwards.
If that didn't resolve the issue, just renamed it back to widget2.html
, and let's have a look at your views.py
, models.py
, and urls.py
(unless you're using it in your admins, in which case, please include that one too), or relevant sections thereof.
I tried to rename widget2 in widget.html w/ any luck. I copy and paste here below the relevant sections of the mentioned files:
views.py
def forum_new_thread(request):
form = ForumThreadForm()
context = {'form': form}
return render(request, 'forum/new_thread.html', context)
models.py
class ForumThread(models.Model):
dj = models.ForeignKey(DjProfile)
user = models.ForeignKey(User, blank=True, null=True)
title = models.CharField(max_length=200)
content = MarkdownxField()
creation_date = models.DateField(auto_now_add=True)
edit_date = models.DateField(auto_now=True)
def __str__(self):
return self.title
urls.py
urlpatterns += i18n_patterns(
...
url(r'^markdownx/', include('markdownx.urls')),
url(r'^new-thread/$', views.forum_new_thread, name='forum_new_thread'),
prefix_default_language=False
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
thanks a lot for your interest in my issue :)
Ok, this is getting interesting!
And your form looks like this?
from django.forms import Form
from markdownx.fields import MarkdownxFormField
class ForumThreadForm(Form):
# ...
content = MarkdownxFormField()
Also, does it work without the customised widget?
If not, perhaps run ./manage.py makemigrations
, ./manage.py migrate
and see if it works?
and you're very welcome. We try our best depending on our time.
slighty different but I think it should be the same:
from markdownx.fields import MarkdownxFormField
from django import forms
class ForumThreadForm(forms.Form):
content = MarkdownxFormField()
makemigations
and migrate
return No changes detected
and No migrations to apply.
(I already run them)
without the customized widget (I mean, without the widget2.html
file) everything works, nothing change!
Ok, I'm going somewhere and will be back to work on this again in about an hour (just so you're not sitting there waiting until then).
Ok... I read this thing all over again.
When you say you don't see any new classes added, what do you exactly mean? I mean, do the editor / preview elements render in your webpage or nothing renders all together? Do you see any errors displayed by Django? Could you check the browser console to see if there are any JavaScript errors?
If they do render, what is it exactly that you are expecting to see? Maybe give an example?
I get the following html:
<form method="POST" action="">
<input type="hidden" name="csrfmiddlewaretoken" value="theToken">
<label for="id_content">Content:</label>
<div class="markdownx">
<textarea name="content" cols="40" rows="10" required="" id="id_content" class="markdownx-editor" data-markdownx-editor-resizable="" data-markdownx-urls-path="/markdownx/markdownify/" data-markdownx-upload-urls-path="/markdownx/upload/" data-markdownx-latency="500" style="transition: opacity 1s ease;"></textarea>
<div class="markdownx-preview"></div>
</div>
</form>
The textarea
is correctly rendered and and I don't get any error in Django or JS console, but I would expect to see the col-md-6
css classe somewhere in the html.
Am I missing something?!
Oh... now I see what you mean.
I can now say for certain that the issue is not caused by the JavaScript (I reviewed that section of the code this morning). There is probably something we're both missing here.
The thing is, the template must be served and rendered automatically by Django when placed in the correct location (it has nothing to do with MarkdownX). You are placing the file in the correct location, but it is still not rendered. All your settings, as far as I can see, appear to be correct too.
So the only thing left here is that Django cannot locate the file for some reason.
We can really force Django to find the file through a small hack, but that wouldn't tell us anything about the reason why the file is not served properly.
Here is how:
forms.py
from django import forms
from markdownx.widgets import MarkdownxWidget
# ----------------------------------------------------------------------------
class CustomMarkdownxWidget(MarkdownxWidget):
template_name = "path_to_your_custom_template" # <====
class CustomMarkdownxFormField(forms.CharField):
def __init__(self, *args, **kwargs):
super(MarkdownxFormField, self).__init__(*args, **kwargs)
if issubclass(self.widget.__class__, forms.widgets.MultiWidget):
is_markdownx_widget = any(
issubclass(item.__class__, CustomMarkdownxWidget)
for item in getattr(self.widget, 'widgets', list())
)
if not is_markdownx_widget:
self.widget = CustomMarkdownxWidget()
elif not issubclass(self.widget.__class__, CustomMarkdownxWidget):
self.widget = CustomMarkdownxWidget()
# ----------------------------------------------------------------------------
class ForumThreadForm(forms.Form):
content = CustomMarkdownxFormField()
Ok, the hack aside (and if it doesn't work, I would seriously think there is an external issue); do you think there might be an app (or middleware) that causes some sort of behavioural change in Django when it comes to serving / rendering templates?
Many thanks for your answer; now i'm travelling, i can check and followup tomorrow morning!
Even the small hack does not solve my issue, I really think it's about Django not locating the template. I share with you my tree, maybe you notice something I'm not doing right
.
├── db.sqlite3
├── frontend
│ ├── admin.py
│ ├── apps.py
│ ├── custom_context.py
│ ├── forms.py
│ ├── __init__.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── ...
...
│ ├── models.py
│ ├── static
│ │ ├── custom.css
│ │ ├── custom.js
│ │ ├── empty.txt
│ │ └── images
│ │ ├── background.jpg
│ │ ├── bckg.png
│ │ ├── dav.jpg
│ │ ├── hopk.jpg
│ │ ├── icons
│ │ │ ├── icon_beatport.png
│ │ │ ├── icon_facebook.png
│ │ │ ├── icon_residentadvisor.png
│ │ │ ├── icon_soundcloud.png
│ │ │ └── icon_youtube.png
│ │ ├── john.jpg
│ │ ├── msl-logo-bianco.png
│ │ └── nobody.jpg
│ ├── templatetags
│ │ ├── helper_tags.py
│ │ ├── __init__.py
│ ├── tests.py
│ └── views.py
├── locale
│ └── it
│ └── LC_MESSAGES
│ ├── django.mo
│ └── django.po
├── manage.py
├── mysoundlist
│ ├── __init__.py
│ ├── local_settings.py
│ ├── production_settings.py
│ ├── settings.py
│ ├── static
│ │ └── empty.txt
│ ├── urls.py
│ └── wsgi.py
├── Procfile
├── README.md
├── requirements.txt
├── runtime.txt
├── templates
│ ├── base.html
│ ├── dj_profiles
│ │ ├── partials
│ │ │ ├── _breadcrumbs.html
│ │ │ ├── _events.html
│ │ │ ├── _producers.html
│ │ │ ├── _threads.html
│ │ │ └── _tracks.html
│ │ ├── show_events.html
│ │ ├── show_events_track.html
│ │ ├── show.html
│ │ ├── show_producers.html
│ │ ├── show_threads.html
│ │ └── show_tracks.html
│ ├── forum
│ │ └── new_thread.html
│ ├── home.html
│ ├── layout
│ │ ├── footer.html
│ │ └── header.html
│ ├── markdownx
│ │ └── widget2.html
│ ├── registration
│ │ ├── login.html
│ │ ├── password_reset_complete.html
│ │ ├── password_reset_confirm.html
│ │ ├── password_reset_done.html
│ │ ├── password_reset_email.html
│ │ ├── password_reset_form.html
│ │ ├── password_reset_subject.txt
│ │ └── signup.html
│ └── user_profiles
│ └── show.html
└── uploads
└── dj_images
I'll come back to this later this evening.
I ended up doing the whole thing in CSS, but if I could override the field template everything would have been easier! So the issue is still pending
What are dal
, and dal_select2
about?
They are related to Django Autocomplete Light
@davideghz could you try that hack thing with a different filename? Like, put that widget2.html in a different directory and rename it to something else all together, then use the new path in the hack I gave you. Let's see if that works.
If that doesn't work either, then when need to find out why is Django failing to serve the templates. Even so it would fall outside the boundaries of MarkdownX, I would still like to find out what this is happening.
INSTALLED_APPS = [ .... 'django.forms', .... ]
FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
@infinity1207 care to elaborate? Why + are there any citations as to why this has happened?
I have the some problem, this topic help me, tnx!
But I'm using Jinja2 renderer...
And I came across a problem: in template context no markdownx_editor variable :( I looked in the code markdownx/widgets.py
if not DJANGO_VERSION[:2] < (1, 11):
return super(MarkdownxWidget, self).render(name, value, attrs, renderer)
No any markdownx_editor passed to render... I am surprised :) This was tested with Jinja2?
Me settings here https://pastebin.com/Rbv4feSR
(intopython_2_env) wad@wad-thinkpad:~/PycharmProjects/intopython (develop)$ pip freeze
Django==1.11.4
django-jinja==2.3.1
django-markdownx==2.0.21
Jinja2==2.9.6
Markdown==2.6.8
@suguby I'm afraid not, this has not been tested on Jinja.
i think you may not add django-bootstrap3
when you installed it
add tab{% bootstrap_css %}
and{% bootstrap_javascript %}
in your widget2.html.
I found the work around for this if interested. It will depend how you have setup templates though.
TEMPLATES = [ {
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
'DIRS': [
str(APPS_DIR.path('templates/markdownx')),
str(APPS_DIR.path('templates')),
],
'OPTIONS': {
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
'debug': DEBUG,
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
# https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
'loaders': [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
],
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
# Your stuff: custom template context processors go here
],
},
},
] add 'django.forms', to installed apps.
Add FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
I struggled with this for a while and the solution provided by @infinity1207 was the one which helped me. Thanks by the way.
@xenatisch @infinity1207 There is a mention of the django.forms
apps being required in the documentation
TemplatesSetting
class TemplatesSetting This renderer gives you complete control of how widget templates are sourced. It uses get_template() to find widget templates based on what’s configured in the TEMPLATES setting.
Using this renderer along with the built-in widget templates requires either:
'django.forms' in INSTALLED_APPS and at least one engine with APP_DIRS=True.
Adding the built-in widgets templates directory in DIRS of one of your template engines. [...]
Using this renderer requires you to make sure the form templates your project needs can be located.
This has to do with the way the markdownx widget calls the template.
Currently it is set to be:
template_name = 'markdownx/widget.html'
However, I think changing that to:
template_name = 'widgets/markdownx/widget.html'
Should reader the template correctly. If I am right, then the only option you have is to use @xenatisch patch. If there should be an update in the future of the package code to correctly call the widgets templates, then this shouldn’t be a problem.
【本信息为自动回复】您发给我的信件已经收到。--世东
Hi, I followed the docs and I created a new BASE_DIR/templates/markdownx/widget2.html file with the following:
Nothing happen when I visit my page, I don't see the new class added.
The form is defined in forms.py as follow:
and in the views.py I have:
My settings.py is:
What am I doing wrong? Thanks!