How should I extend the Django FeinCMS MediaLibrary? - django

We would like to extend the MediaLibrary of the Django FeinCMS without editing the module code itself.
We want
a few custom fields
and to use a library for individual cropping that we have already.
How should we put everything together?
The simplest approach would be to create an extensions model with a ForeignKey to the MediaLibrary, and to register a custom Admin site with an inline admin for the extensions model. But maybe there's a cleaner and better way.

As Hedde said, the media file model supports registering extensions the same way as the page module allows, using MediaFile.register_extensions.
The method which is used for generating thumbnails in the media library should always be FEINCMS_MEDIALIBRARY_THUMBNAIL. The default value of this setting is feincms.module.medialibrary.thumbnail.default_admin_thumbnail which is a method that receives a media file object and returns the URL to a thumbnail or None.

Related

Django Haystack override class's index_queryset in subclass

I'm using Django Haystack (with Aldryn Search) to search content on a client site. However, we need to modify the Articles indexed from the Aldryn NewsBlog plugin - Articles assigned to the Intranet Section should not be indexed. So I made a subclass in my plugin to override that like the documentation says to do:
Subclasses can override this method to avoid indexing certain objects.
However, when I try to rebuild the index it says:
aldryn_newsblog.models.Article has more than one 'SearchIndex`` handling it. Please exclude either aldryn_newsblog.search_indexes.ArticleIndex object or search_modifier.search_indexes.BlogHelperIndex object
The documentation is not clear to me what I need to write to have this modify the existing index from the NewsBlog plugin. I don't want to totally exclude it like the error is suggesting, but to subclass it like the documentation says to do.
Here is my search_indexes.py file:
from aldryn_newsblog.search_indexes import ArticleIndex
class BlogHelperIndex(ArticleIndex):
def index_queryset(self):
# make sure only public posts are pulled
return self.get_model().objects.exclude(app_config__app_title='DirectConnection')
I'm a moron. Aldryn Newsblog provides a simple checkbox in the Sections' settings to enable/disable indexing of that section without the need for a code change.

Do I need to create forms.py for my forms in Django?

I'm about to create a form in my website made in Django with elements that have complex input types from different plugins (like calendar plugins). Also, I'll be using a Validator plugin which validates the input before submission.
My question is do I need to create forms.py and like model the form or can I just create the form manually? The former seems like a very hassle process. Which one is more efficient and recommended?
As #dmitryro said you can create your forms manually in the templates and then getting in the request. It's recommended to use the forms api provided by Django since it allows you to reuse, validate, and customize your forms.
As to whether or not it is a good practice that depends completely on you but if you are trying to scale an application I would recommend use the forms.
It is good to use Django's built in form.
If we use django's form then we only have to write python code and django will create corresponding html for it. And our code will be short and clean.

How can I change ImageField widget in Mezzanine to use Media library browser?

When I use common Source class definition like
class Source(models.Model):
photo = models.ImageField(upload_to=...)
...
I get the common dialog in the administration module which shows currenty assigned photo or empty field. In the latter case I am able to select the photo from the file browser operating on local disk.
If I change the blog picture, I am able to assign only the photos downloaded to media library and available through Media library browser.
What should I do to be able to select a photo from Media library browser also for ordinary ImageField?
Why are there two ways to do the same thing?
I was able to get it working by using FileField instead of ImageField.
from mezzanine.core import fields
class Source(models.Model):
photo = fields.FileField("Image", upload_to="dir/", format="Image")
Digging through the code a bit, I found that Mezzanine's 'FileField' is just an abstraction for filebrowser's 'FileBrowserField' if it exists, otherwise it falls back to the default django FileField. I don't know why they didn't make it work for ImageField as well. FileBrowserField is smart enough to look it up from the media library, FileField is not. So you will also need to have filebrowser_safe installed.

TinyMCE plugin custom tags in Django

I am building a custom image insert plugin for TinyMCE. The idea is that each article already has a relationship with a collection of images through an ArticleImage model which allows the user to provide an article-specific caption. The TinyMCE will then insert a custom tag (something like <myapp:image image-id="9389" caption="Caption override">) which is rendered as a preview of the image and caption in the editor, and rendered into <figure><img src="images/9389.jpg" /><figcaption>Caption override (Photo: photographer)</figcaption></figure>. This could equally be something like <myapp:poll> or <myapp:video>.
My question is: what is the best way (and where is the best place) to parse this 'dummy tag' into its rendered HTML in the Django view?
Or is there another, better approach?
IMHO, the best place to render custom markup, is in the template via a templatefilter.
I would risk myself to say that using a templatefilter to render custom markup is the "djangoish" way, since that's the way to go with django.contrib.markup.
Storing the custom tag in the model is a good idea, because then you can change the template filter implementation, which would be impossible if the custom tag is processed before storage.

Django: How to dynamically add tag field to third party apps without touching app's source code

Scenario: large project with many third party apps. Want to add tagging to those apps without having to modify the apps' source.
My first thought was to first specify a list of models in settings.py (like ['appname.modelname',], and call django-tagging's register function on each of them. The register function adds a TagField and a custom manager to the specified model. The problem with that approach is that the function needs to run BEFORE the DB schema is generated.
I tried running the register function directly in settings.py, but I need django.db.models.get_model to get the actual model reference from only a string, and I can't seem to import that from settings.py - no matter what I try I get an ImportError. The tagging.register function imports OK however.
So I changed tactics and wrote a custom management command in an otherwise empty app. The problem there is that the only signal which hooks into syncdb is post_syncdb which is useless to me since it fires after the DB schema has been generated.
The only other approach I can think of at the moment is to generate and run a 'south' like database schema migration. This seems more like a hack than a solution.
This seems like it should be a pretty common need, but I haven't been able to find a clean solution.
So my question is: Is it possible to dynamically add fields to a model BEFORE the schema is generated, but more specifically, is it possible to add tagging to a third party model without editing it's source.
To clarify, I know it is possible to create and store Tags without having a TagField on the model, but there is a major flaw in that approach in that it is difficult to simultaneously create and tag a new model.
From the docs:
You don't have to register your models
in order to use them with the tagging
application - many of the features
added by registration are just
convenience wrappers around the
tagging API provided by the Tag and
TaggedItem models and their managers,
as documented further below.
Take a look at the API documentation and the examples that follow for how you can add tags to any arbitrary object in the system.
http://api.rst2a.com/1.0/rst2/html?uri=http://django-tagging.googlecode.com/svn/trunk/docs/overview.txt#tags
Updated
#views.py
def tag_model_view(request, model_id):
instance_to_tag = SomeModel.objects.get(pk=model_id)
setattr(instance_to_tag, 'tags_for_instance', request.POST['tags'])
...
instance_to_tag.save()
...returns response
#models.py
#this is the post_save signal receiver
def tagging_post_save_handler(sender, instance, created):
if hasattr(instance, 'tags_for_instance'):
Tag.objects.update_tags(instance, instance.tags_for_instance)