Widget error with TinyMCE in Django - python

I'm getting this error with TinyMCE in django:
TypeError: init() got an unexpected keyword argument 'widget'
I have followed the instructions as I found them, and don't know why the error is there. Here is the model:
class Article(models.Model):
"""Represents a wiki article"""
title = models.CharField(max_length=100)
slug = models.SlugField(max_length=50, unique=True)
text = models.TextField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))# (help_text="Formatted using ReST")
author = models.ForeignKey(User)
is_published = models.BooleanField(default=False, verbose_name="Publish?")
created_on = models.DateTimeField(auto_now_add=True)
objects = models.Manager()
published = PublishedArticlesManager()
The comment "#formatted in ReST" is because the original TextField was using restructuredText. I was able to actually get tinyMCE from CDN and place a very simpel script in the head of the appropriate template. It loaded the wysiwyg editor, but then rendered the saved page with HTML tags visible.
So I added to form declaration as:
from django import forms
from models import Article, Edit, FileUploadHandler
from tinymce import models as tinymce_models
class ArticleForm(forms.ModelForm):
class Meta:
text = forms.Charfield(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))#(help_text="Formatted using ReST")
model = Article
exclude = ['author', 'slug']
class EditForm(forms.ModelForm):
class Meta:
model = Edit
fields = ['summary']
class UploadImageForm(forms.ModelForm):
class Meta:
model = FileUploadHandler
image = forms.ImageField()
fields = ['title']
The editor is there, but upon save its rendering the article with html tags visible. Why is that?

widget is an attribute for form fields, not model fields. You need to move that setting to your form declaration (or formfield_overrides if you're trying to use it in the admin).
To display the marked up content without escaping the HTML tags in a later view, one way is to use the |safe built in filter.

Related

Django Model Field Inline

In Django, you can use inline to make new instances of models by just clicking the add instance button on the bottom of the admin site.
Is there a way to do this for a model field inside a model.
For example, if you were cataloging a book and you want to capture all the chapters in each books name. Every book has a different number of chapters so you could not just do
chapter1 = CharField(max_length = 200)
chapter2 = CharField(max_length = 200)
and so on. Like the picture below but not for model instances for model fields.
Yes, you can model the Book and its chapters with:
class Book(models.Model):
title = models.CharField(max_length=256)
class Chapter(models.Model):
title = models.CharField(max_length=256)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
then we can work with a TabularInline [Django-doc], and write this as:
from django.contrib import admin
class ChapterInline(admin.TabularInline):
model = Chapter
class BookAdmin(admin.ModelAdmin):
inlines = [
ChapterInline,
]

Having admin inline for model without direct relation or foreign key

So, I have this these model:
class Media(models.Model):
title = models.CharField(max_length=50, blank=True)
slug = models.SlugField(max_length=70, blank=True, editable=False)
class Meta:
abstract = True
class Photo(Media):
source = models.ImageField(upload_to='uploads/gallery/photo')
class Video(Media):
source = models.FileField(upload_to='uploads/gallery/photo')
class Item(models.Model):
content_type = models.ForeignKey(
ContentType,
limit_choices_to={'model__in': ['photo', ]},
on_delete=models.CASCADE,
)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
class Album(Media):
items = models.ManyToManyField(Item)
How can I have an album admin with photo and video as inline so i can upload photo and video when i created an album ?
When I tried making inline for photo and hook it to album admin, I get error "photo has no foreignkey to album", pretty obvious, from there I think there should be a way to link foreignkey needed by album admin with content object from model item.
Note: I specifically doesn't want an item admin. An item are created at model post save signals.
I do not think this works out of the box. But you can use libraries like eg django-smart-selects-generics. Depending on your django version you might need to update some files there.
Installation works with:
pip install django-smart-selects-generic
You also need to have django-smart-selects installed.
Then add both apps in the settings.
INSTALLED_APPS = (
...
'smart_selects',
'smart_generic'
)
And then in your admin.py you can do:
from smart_generic.form_fields import GenericChainedModelChoiceField
from django.forms.models import ModelForm
class TForm(ModelForm):
object_id = GenericChainedModelChoiceField('content_type','content_type',label=u'Content object',queryset=TargetRelation.objects.all())
class Meta:
model = TargetRelation
fields = ['target','content_type']
class TRAdmin(admin.ModelAdmin):
form = TForm
class TRInline(admin.TabularInline):
model = TargetRelation
form = TForm
class PlanetAdmin(admin.ModelAdmin):
inlines=[TRInline,]
Depending on your django version you might need to replace in widgets.py:
Media = ChainedSelect.Media
by
.media = ChainedSelect.Media
And in smart_select views.py add:
import json as simplejson
and replace the return statement by:
return HttpResponse(json, content_type='application/json')

How to relative urls in Django URLField

How i can get relative urls in my field after serialize? now i get abolute.
My model:
class Article(models.Model):
title = models.CharField(max_length=120)
image = models.ImageField()
text = models.TextField()
link = models.URLField()
And serializer:
class ArticleSerializer(ModelSerializer):
link = URLField()
class Meta:
model = Article
fields = '__all__'
Actually, without the http://... prefix, the url will not be a valid url. If you want to link somewhere inside your app, you can take the output of something like django's reverse and store it in a CharField (or just do some string manipulation by declaring a method, prior to inserting to the database or prior to serialization-deserialization).

Django REST framework: nested relationship: non_field_errors

In a Django-REST-framework project I tried to use the nested relationship and got a "non_field_errors" in the browsable API web view.
The code is from this part of the documentation: http://www.django-rest-framework.org/api-guide/relations#nested-relationships
models.py:
from django.db import models
class Album(models.Model):
album_name = models.CharField(max_length=100)
artist = models.CharField(max_length=100)
class Track(models.Model):
album = models.ForeignKey(Album, related_name='tracks')
order = models.IntegerField()
title = models.CharField(max_length=100)
#duration = models.IntegerField()
class Meta:
unique_together = ('album', 'order')
ordering = ('order',)
def __unicode__(self):
return '%d: %s' % (self.order, self.title)
serializers.py:
from rest_framework import serializers
from myapp.models import Album, Track
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ('order', 'title')
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
ERROR (at ../albums):
The Track input field is marked red with the error message: non_field_errors.
Clicking the OPTIONS button reveals the actual&correct data structure:
Tracks nested with their appropriate propertie
The raw data input of the browsable browser view shows:
{
"album_name": "",
"artist": "",
"tracks": null
}
Posting some valid raw-data actually works. But it'd be nicer if the web interface form would work as well. Especially since I'm wondering if there's something funny going on anyway.
Thank you in advance!
I have experienced this issue as well. One way to get rid of the error is to use:
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.RelatedField(many=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
However, this removes the nested track fields and displays only a string representation of the tracks.
Edit: I figured it out. What you want is this:
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
read_only_fields = ('tracks',)
depth = 1
This will cause the tracks to nest without throwing the UI error.
One solution is to simply hide the HTML form on the browser side. For example, override Rest Framework's api.html template (by creating your_app/templates/rest_framework/api.html) and include the following:
{% extends "rest_framework/base.html" %}
...
{% block script %}
{{ block.super }}
<script>
$('.form-switcher a[name="html-tab"]').hide();
$('.form-switcher a[name="raw-tab"]').tab('show')
</script>
{% endblock %}
If you want to keep the HTML form for your flat endpoints and simply remove it from your nested ones, you could use the name variable as an indicator. For instance, include "Nested" in the names of your nested endpoints and do something like this:
if("{{ name }}".indexOf("Nested") >= 0){
$('.form-switcher a[name="html-tab"]').hide();
$('.form-switcher a[name="raw-tab"]').tab('show').hide();
}

Reverse Relation Search Django Admin Interface

Is it possible to do a reverse relation search on the Django Admin interface?
My Django app database schema consists of the following models:
class Tag(models.Model):
title = models.CharField(max_length=50)
class Publication(models.Model):
title = models.CharField(max_length=200)
tags = models.ManyToManyField(Tag, blank=True, related_name="publications")
I have added a search field for looking up tags by title in my admin.py file by doing:
class TagAdmin(admin.ModelAdmin):
list_display = ('title',)
search_fields = ('title',)
Thus, when I type a tag title into the search field on the django admin interface, a list of matching tag titles comes up. Now I'd like to make it so that if I type a tag title into the search field, matching publications come up.
In other words, I'm imagining something like:
class TagAdmin(admin.ModelAdmin):
list_display = ('title',)
search_fields = ('publications',)
Which of course doesn't work... but that's the idea...
Is this even possible? And/or am I even going about this the right way? If so, could someone suggest a way to do this or a resource? If you are kind enough to do so, please keep in mind that I am very much a beginner. Thanks.
You shouldn't try to do this using an admin class registered to your Tag model. Instead, set up an admin class for Publication and set its search_fields:
class PublicationAdmin(admin.ModelAdmin):
list_display = ('title',)
search_fields = ('tags__title',)

Categories

Resources