Hello,

I want to display images in my manyTomany so that a user can choose what 
images would be included inside of a "BlogWidgetCarousel". The issue I am 
running into is that the render function for the widget returns html via 
the "format_html" and the variable has lost its "safe" setting at that 
point.

In my model I return the choice_label with "mark_safe" but somewhere along 
the way the string is altered and it must be losing that quality. (For the 
example I just changed it to a <b> tag)

I have found the render method and confirmed that I can set the string back 
to a safe state and it works fine.

My questions

   1. Am I just making some kind of mistake when I try to send back the 
   string from the model?
   2. Am I doing something that is unexpected? It seems like this should 
   work.
   3. Would you create a custom widget to solve this issue, if not what 
   would you use?
   



#models.py
class BlogWidgetCarousel(models.Model):
    entry = models.TextField()
    blog = models.ForeignKey(Blog, blank=True, null=True)
    position = models.PositiveSmallIntegerField("Position")
    images = models.ManyToManyField("Image")

    class Meta:
        ordering = ('position', )

    def __str__(self):
        return str(self.position)
    
    def save(self, *args, **kwargs):
        self.entry = "<b><i>TODO: create image slider</i></b>"
        super(BlogWidgetCarousel, self).save(*args, **kwargs)

    def display(self):
        return self.entry

class Image(models.Model):
    title = models.CharField(max_length=60, blank=False, null=False)
    image = models.ImageField(upload_to="images/")

    def thumb(self):
        return '<a href="{0}"><img src="{0}"></a>'.\
                    format(MEDIA_URL + str(self.image))

    def __str__(self):
        return mark_safe(u'<b>bold</b>')
    __str__.allow_tags = True


#admin.py
class BlogWidgetCarouselInline(admin.StackedInline): #, SortableInline):
    model = BlogWidgetCarousel
    extra = 0

    formfield_overrides = {
        models.ManyToManyField: {'widget': CheckboxSelectMultiple},
    }

    fieldsets = (
        ("Create Carousel:", {
            'fields': (("position"), 'images',)
        }),
        ("Result:", {
            'fields': ('thumb', 'display_as',)
        }),
    )
    readonly_fields = ('display_as', 'thumb',)

    def display_as(self, instance):
        return instance.display()
    display_as.allow_tags = True

    def thumb(self, instance):
        x = ""
        for i in instance.images.all():
            x += i.thumb()
        return x 
    thumb.allow_tags = True

class EntryAdmin(admin.ModelAdmin):
    list_display = ("title", "created")
    prepopulated_fields = {"slug": ("title",)}
    inlines = [
                BlogWidgetTextInline, BlogWidgetCarouselInline,
            ]


#dist-packages/django/forms/widgets
#...
@html_safe
@python_2_unicode_compatible
class ChoiceInput(SubWidget):
    """
    An object used by ChoiceFieldRenderer that represents a single
    <input type='$input_type'>.
    """
    input_type = None  # Subclasses must define this

    def __init__(self, name, value, attrs, choice, index):
        self.name = name
        self.value = value
        self.attrs = attrs
        self.choice_value = force_text(choice[0])
        self.choice_label = force_text(choice[1])
        self.index = index
        if 'id' in self.attrs:
            self.attrs['id'] += "_%d" % self.index

    def __str__(self):
        return self.render()

    def render(self, name=None, value=None, attrs=None, choices=()):
        if self.id_for_label:
            label_for = format_html(' for="{}"', self.id_for_label)
        else:
            label_for = ''
        attrs = dict(self.attrs, **attrs) if attrs else self.attrs
        #print self.choice_label <---- Prints "<b>bold</b>" as expected.
        return format_html('<label{}>{} {}</label>', label_for, 
self.tag(attrs), self.choice_label) # choice_label is escaped by format_html
        #return format_html('<label{}>{} {}</label>', label_for, 
self.tag(attrs), mark_safe(self.choice_label)) <---Works


-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/e4d7ef94-181c-4f09-8471-e038455793e6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to