Django: Problems embedding tinyMCE into my non-flatpage model - django

I got tinyMCE working for flat pages by copying the change_form.html file and embedding a script element.
I followed the directions here but still have issues. I added this snippet to my Entry model:
class Entry( models.Model ):
class Admin:
# various admin options are here
js = (
'/tiny_mce/tiny_mce.js',
'/appmedia/admin/js/textareas.js',
)
When I view source in my add entry admin page ( after restarting Apache2 ) I don't see the above referenced js files anywhere.

The directions you linked to are very old, and in particular date back to before the 'newforms-admin' changes were made. You need to add the js tuple to your admin class's inner Media class, as described here.

Ended up resorting to django-tinymce, had to modify my app's admin.py and define a class for the AdminForm, override the form attribute with my newly created class, and tinyMCE finally showed up.

Related

How to make raw text file (to edit robots.txt) editor in Django Wagtail admin

The goal is to create a text file editor within the Wagtail admin site.
Specifically for robots.txt file. I want the admin to update the file from the admin.
How can I do that?
There are some considerations to make for the robots.txt file hitting your server and doing a database read each time. You probably will want to consider some kind of caching layer here, however I have answered assuming you will resolve that and just want to get a Wagtail 'editor' solution here.
Wagtail provides a contrib.settings module that allows you to have a settings model per site. This is a very helpful module that allows users, usually admin only users, to modify content that is specific to a site but does not suit the idea of a 'page'.
https://docs.wagtail.org/en/stable/reference/contrib/settings.html
Settings model
In your app's models.py file - set up a new settings model.
from django.db import models
from wagtail.admin.panels import FieldPanel
from wagtail.contrib.settings.models import BaseSetting, register_setting
#register_setting
class MySettings(BaseSetting):
robots = models.TextField(blank=True)
panels = [
FieldPanel('robots'),
]
robots.txt view & template
There are lots of ways to load a View with robots.txt
Accordbox has a good tutorial on how to set up a robots.txt view https://www.accordbox.com/blog/wagtail-seo-guide/#robotstxt
Once you have your view, you can get the settings output via the model class.
# using in your view
def robots_view(request):
robots = MySettings.for_request(request).robots
## return the content in your view
Alternatively you can use in your template context via an injected template context variable
note: 'wagtail.contrib.settings.context_processors.settings' must be added to context_processors
User-agent: *
{{ settings.app_label.MySettings.robots }}
Considerations
If possible, it would always be better to serve a static file here, or strongly cache this value at a minimum.
Validation is a must - make it hard for your editors to break your website, remember that search engines only crawl this semi-regularly and breaking this could mean a few days of de-listing or broken listings if your editors are not careful.
Permissions are a must, maybe even a two step process to push these changes live somehow?
You could possibly put a robots field on your HomePage model and access the data in your robots view. This kind of breaks the concept of this model only reflecting the home page but then extending to the 'root' content.

How can include a regular Django view content in a Wagtail page?

I have a website running on Django that uses Wagtail for most of the pages (that are simply text content, editable through the Wagtail Admin UI). However, I have some content that needs to be dynamically rendered from my own Django model (let's say it's a list of handouts). I'd like that content to be rendered on a Wagtail page that would also have some Wagtail models (e.g., top menu, some introductory text). What's the best way to do this? I thought about making the list of handouts an API endpoint, and rendering it with JavaScript + XHR, but it seems like there should be a good way to do it server-side.
Assuming the introductionary text is a block in a Wagtail StreamField, you could also define a Wagtail Block that links to a Django model. https://pypi.org/project/wagtail-modelchooser/ is a useful extension that provides this functionality. This makes it possible to render things from Django model instances in your Wagtail stream content.
One option would be to create a property on your Page model that retrieves whatever you are looking for from this other model
# rest of your imports
...
from handouts import Handouts
class MyPage(Page):
# rest of your page's fields
...
#property
def get_handouts(self):
handouts = Handouts.objects.all()
return handouts

Flask-Admin: Adding a WYSIWYG editor to an inline model?

Pretty much as the subject has it: I have a Flask-Admin site, and would like to add TinyMCE or CKEditor to a textarea in an inline model.
There are various instructions for adding CKEditor to Flask-Admin in general, e.g. Flask-Admin and CKEditor WYSIWYG textarea integration and Getting CKEditor to work with Flask-Admin. I've followed these to create the WTForms widget and field. The inline models don't use edit.html, for pulling in the JS, but I can add it to the master template, though this is not ideal.
But the main issue is how to attach the WTForms field to the Flask-Admin model. The existing instructions have you set a form_overrides = dict(fieldname=CKTextAreaField). But that doesn't work inside inline_models. How do I accomplish this?
I had this issue a few days ago and managed to solve it by adding this to my view class.
class CustomView(ModelView):
extra_js = ['//cdn.ckeditor.com/4.6.0/standard/ckeditor.js']
inline_models=[ ( YourModel, dict(
form_overrides={
'FieldName':CKTextAreaField
}
))]
Assuming that you followed the flask admin docs tutorial for CKEditor.
inline_models consist of (model, options) pairs. The "options" object is the key here: it accepts most of the form_* attributes that ModelView has.

How to unregister Mezzanine's Quick Blog from the Django admin dashboard?

I'm subclassing mezzanine's BlogPost and have unregistered it to prevent it from showing in the admin page. e.g.
class BlogPostAdmin(admin.ModelAdmin):
fieldsets = ((None, {"fields": ("title",)}),)
def in_menu(self):
for(name, items) in settings.ADMIN_MENU_ORDER
if "blog.BlogPost" in items:
return True
return False
admin.site.unregister(BlogPost)
admin.site.register(BlogPost, BlogPostAdmin)
However, this does not unregister the Quick Blog from the admin page.
How do I prevent quick blog from showing up in the admin page?
The docs don't explain how to do this(http://mezzanine.jupo.org/docs/admin-customization.html#dashboard)
Did you try to remove "blog_tags.quick_blog" from DASHBOARD_TAGS setting ?
inside your project create below folder structure
-templates -> admin -> includes
and inside includes folder create blank html called as quick_blog.html.
Thats it!
p.s "->" means folder inside folder mentioned before

Django grappelli adding custom js to change_form

I try to add my custom javascript to some change_form templates.
Before having installed Grappelli, I could do that by extending
change_form.html of admin and creating sub folders under the templates
with my module names.
For example my tree hireachy was like :
+templates
++admin_copies
+++change_form.html (I have added extra js blocks)
++admin
+++employer
++++employer
+++++change_form.html
++++employer_new
+++++change_form.html
As you understand I have a model named "Employer". I can add my custom
js methods under the change_form.html files.
However, this kind of inheritance cause javascript/breadcrumbs
problems with Grappelli.
How can I add simply my custom javascript functions for each model
separetly ?
Create a subclass of ModelAdmin, and define the custom js in its Media class.
admin.py, in the same folder as the models.py that has Employer:
from django.contrib import admin
from models import Employer
class EmployerAdmin(admin.ModelAdmin):
class Media:
js = ("js/custom.js",) # This paths are appended to your MEDIA_URL setting
admin.site.register(Employer, EmployerAdmin)
Read more here