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.
Related
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.
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
I want to implement in Django Admin a jquery plugin that "adjust" and image(http://guillotine.js.org/), them get the coordinates with ImageKit and save the new image.
I need some tutorials and advises how to do it.
I have no tutorials, but can give you advice.
You can customize your admin model with custom css and js, by Media class, like so:
class MyModelAdmin(admin.ModelAdmin):
class Media:
css = {
"all": ("my_styles.css",)
}
js = ("my_code.js",)
You can look in dev tools, how Django chose names id's and classes for elements in page and also check the docs.
Admin docs
i have a Model for a user profile in my django app that has a models.ImageField and i have an ModelAdmin for it
when a user uploads an image , in the admin page , when i go in that user's Customize page , in the ImageField section , there is the url of uploaded image and a checkbox named "Clear" and a button for updating the image. how can i change the text of that checkbox ? for example i want it to have the text "Delete" instead of "Clear"
It seems like "Clear" is hardcode.
So either you create a custom widget simply like that:
class MyClearableFileInput(ClearableFileInput):
clear_checkbox_label = ugettext_lazy('Delete')
And assign it to your form field like that
MyForm(forms.Form):
myfile=ImageField(widget=MyClearableFileInput)
Or add overwrite it in your admin
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.ImageField: {'widget': MyClearableFileInput},
}
Or you use the translation mechanisms to translate Clear into Delete. Django translation is described in the docs pretty well.
I personally, just think that it is quite some overhead for your problem, unless you are using translations anyway. I would clearly recommend the custom widget - the addtional code is really minimal.
I have a tinymce textarea in my django admin and I need users to be able to upload images (via AJAX) that will be linked in this textarea.
That would be accomplished by adding an "Image Upload" button (it's already working) in the top of the "Content" textarea.
What's the recommended way of doing that?
I can think on 2 solutions:
extending change_form and replacing {% for fieldset in adminform %} for the actual fields... and when it's the content field, I add this value
dynamically adding this button with javascript (find out where the content field is and add a <div> before it)
A better solution, if possible, would be to override just this specific field in the admin templates. Is that possible? Or are there better solutions?
PS: this field is not part of the DB (it just uploads one or more images, saves it to the storage and returns a link that will be included on the tinymce).
maybe you could use this
formfield_overrides from the djangodocs
if not, create a subclass of modelform and overide the form of admin with ModelAdmin.form.