WMD Preview Doesn't Match Output - python

I am using WMD in a google app situation whereby the site administrator can update the pages of the site and the users see the information.
The preview function is working fine and I can see the text the way I want it to appear, but when I am in the users section, the markdown is being returned without the formatting - how can i fix this?
This is the code i am using
{% block content-left %}
{% if is_admin %}
<div id="content-bodyleft" class="wmd-preview"></div>
<form action="/admin/content/" method="post">
<textarea id="markdown" name="markdown" style="width: 400px; height: 200px;" >{{ page_content.html }}</textarea>
<input name="page" type="hidden" value="{{ request.path }}" />
<input type="submit" name="Save" />
</form>
<div class="wmd-output"></div>
<script type="text/javascript">
// to set WMD's options programatically, define a "wmd_options"
// object with whatever settings
// you want to override. Here are the defaults:
wmd_options = {
// format sent to the server. Use "Markdown" to return the markdown source.
output: "Markdown",
// line wrapping length for lists, blockquotes, etc.
lineLength: 40,
// toolbar buttons. Undo and redo get appended automatically.
buttons: "bold italic | link blockquote code image | ol ul heading hr",
// option to automatically add WMD to the first textarea found.
// See apiExample.html for usage.
autostart: true
};
</script>
<div class="wmd-output"></div>
<script type="text/javascript" src="/static/wmd/wmd.js"></script>
{% else %}
{{ page_content.html|markdown }}
{% endif %}

The reason this is happening is because the Django Form is only seeing the value of the <textarea> tag that represents WMD editor. That value is the actual markdown, not the rendered HTML that you see in the preview.
There are several ways to fix this, on either the client or the server...
When the form is saved, convert the markdown to HTML on the server using a python markdown module, like this one
When the form is submitted on the client, have javascript replace the value of the WMD <textarea> tag to the actual HTML
Option #1 is probably the easiest. Here's some sample code...
import markdown
class MyModel(models.Model):
text = models.TextField()
def save(self, force_insert=False, force_update=False):
if self.text:
self.text = markdown.markdown(self.text)
super(MyModel, self).save(force_insert, force_update)

This doesn't appear to have anything to do with WMD.js, which is an editor and has nothing to do with displaying the content.
You don't post your models, but it looks like you are entering content into the "markdown" field, but displaying a different field, "html". I presume you have something in your models - maybe on save - that populates that html field with the converted markup?
Also are you sure you're seeing raw markdown, or are you seeing raw HTML? I would assume you would need to unescape the html output:
{{ page_content.html|safe }}

This is my models.py file
# models.py
from google.appengine.ext import db
class GoogleToken(db.Model):
session_token = db.StringProperty()
scope_url = db.StringProperty()
added_on = db.DateTimeProperty(auto_now_add=True)
class PageContent(db.Model):
html = db.TextProperty()
page = db.StringProperty()
class PageMedia(db.Model):
name = db.StringProperty()
type = db.StringProperty()
content = db.BlobProperty(default=None)
class Announcement(db.Model):
title = db.StringProperty()
content = db.TextProperty()
added_on = db.DateTimeProperty(auto_now_add=True)
and this is from views.py
def content(request):
html = request.POST.get('markdown', None)
page = request.POST.get('page', None)
logging.debug(html)
logging.debug('Page: %s' % page)
query = PageContent.all().filter('page =', page)
page_content = query.get()
if page_content == None:
page_content = PageContent(html=html,page=page)
else:
page_content.html = html
To help you understand what is happening, for example I am typing
Title
----
*Subtitle*
Text text text
and seeing
Title
Subtitle
Text text text
in preview, but on output i am seeing
Title----*Subtitle*Text text text
Thanks, I do appreciate your help with this.

Related

Django textarea form

i need to set rows and cols for a textarea in my HTML page from Django but it doesnt work.
I already put rows and cols in mine form
Views.py
class EditForm(forms.Form):
title = forms.CharField(widget=forms.TextInput(attrs={'name':'title'}))
body = forms.CharField(widget=forms.Textarea(attrs={'name':'body', 'rows':3, 'cols':5}))
def new(request):
return render(request,"encyclopedia/handlepage.html", {
"title": "CREATE NEW PAGE",
"edit": False,
"editpage": EditForm()
})
handlepage.html
{% extends "encyclopedia/layout.html" %}
{% block title %}
{{ title }}
{% endblock %}
{% block body %}
<h1>{{title}}</h1>
Markdown guides
{% if edit %}
//Useless right now
{% else %}
<form method="POST" action="{% url 'save' %}">
<input type="submit" value="SAVE ENTRY"><br>
{% csrf_token %}
{{ editpage }}
</form>
{% endif %}
{% endblock %}
Then my page should have a small text area but it have the same size independent by its row and cols like this
I had the exact same issue and I think we are working on the same project because the screenshots look the same: was this Project 1 for
CS50’s Web Programming with Python and JavaScript?
Anyway, I tried with
content = forms.CharField(widget=forms.Textarea(attrs={"rows":"5"}))
and it looked like it didn't work, but it was only because of a CSS property already applied that overrides the rows and columns attributes (as #AMG also suggested).
You can see this if you open your browser Inspector:
You just need to remove those two CSS properties for width and height to see the rows and columns attibutes apply.
I know that you have probably already solved this issue, but I'm posting this because I guess that fellow CS50 students may still need this answer in the future.
Does adding it in init work? I forget the reason I had to do it this way but it's what I've been using (I may be out of date though).
class EditForm(forms.Form):
body = forms.CharField(widget=forms.Textarea())
def __init__(self, *args, *kwargs):
super().__init__(*args, *kwargs)
self.fields['body'].widget.attrs['rows'] = 3
or alternatively in meta:
class EditForm(forms.Form):
# your fields defined here followed by Meta
class Meta:
fields = ['title', 'body' ]
widgets = {
'body': forms.Textarea(attrs={'rows': 3}),
}
Write those numbers in the quotes. And see if it works.
body = forms.CharField(widget=forms.Textarea(attrs={'name':'body', 'rows':'3', 'cols':'5'}))
What worked for me is changing the CSS style of the text-area.
class EditForm(forms.Form):
title = forms.CharField(widget=forms.TextInput(attrs={'name':'title'}))
body = forms.CharField(widget=forms.Textarea(attrs={'name':'body',
'style': 'height: 3em;'))
Hope it works for you!
I think I have found the answer.
in Project1\wiki\encyclopedia\static\encyclopedia.there is a CSS file called
style.CSS.
in this file determines the Style of textarea.
"
textarea {
height: 90vh;
width: 80%;
}
"
enter image description here
delete this and all come back.

Opening a user uploaded PDF in django

I have a webapp where a user can upload a pdf file. I want the user to be able to click a button to be able to see the file in the browser.
I'm not sure how to link the pdfs as when they are uploaded they get given a random name by django in my static root. eg: hello_0akcjs.pdf
My View
def pdf_view(request, pk):
Menufile = Menu.objects.get(pk=pk).menuFile
with open('Menufile', 'r') as pdf:
response = HttpResponse(pdf.read(), content_type='application/pdf')
response['Content-Disposition'] = 'inline;filename=some_file.pdf'
return response
URL
path('<int:pk>/', pdf_view, name='pdf_view'),
Model
class Menu(models.Model):
name = models.CharField(max_length=50)
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
menuFile = models.FileField(upload_to='menus')
Template
{% for menu in menus %}
View Menu {{ menu.name }}
{% endfor %}
As it stands, everything works, except i just dont know how to get the pdf to be rendered at the URL for that model instances PK.
I was making it far too complicated. All i needed to do was reference the menuFile URL in the template.
Example:
View Menu
To display a pdf you have to use an embed tag,
<embed src={% url 'pdf_view' menu.pk %} width="500" height="375" type="application/pdf">

Text area not reading HTML

I have Django´s Blog APP installed, all working fine, but I need to add posts (via admin) with HTML in the post content field, now, the text area can only read plain text (it doesn´t render HTML).
This is the field:
(models.py)
content = models.TextField()
This is the HTML for this field:
<h6 class="card-text" ><small>{{post.content|slice:":500" |linebreaks |safe}}</small></h6>
Question is: are there special configs for Django/Python in order for the field to render HTML?
The safe tag should already do that... have you tried this:
{% autoescape off %}
{{ post.content }}
{% endautoescape %}
https://code.djangoproject.com/wiki/AutoEscaping
Hope this helps!

Flask SQLalchemy - many to many - show photo with all tags (or blog with all posts etc)

I am new to Flask and SQLalchemy. Want to have web page with individual photo that shows all tags assigned to that photo.
I have SQLalchemy working fine with MYSQL db. Nicely retrieves records etc.
I need help with flask/SQLalchemy work flow:
model -> view (input from url eg view / photo id) -> template -> web page
The models are as follows:
class Photos(db.Model):
id = db.Column(db.Integer, primary_key=True)
filename = db.Column(db.String(100))
tags = db.relationship(
'Tags',
secondary=photo_tags,
backref='photos')
class Tags(db.Model):
id = db.Column(db.Integer, primary_key=True)
tagname = db.Column(db.String(100))
photo_tags = db.Table('photo_tags',
db.Column('tag_id', db.Integer, db.ForeignKey('tags.id')),
db.Column('photo_id', db.Integer, db.ForeignKey('photos.id'))
)
My view is as follows:
#app.route('/phototags/<int:id>')
##login_required
def phototags(id=None):
photo_tags = Tags.query.filter(Tags.photos).filter(id == id).all()
return render_template(
'phototags.html',
title='PhotoTags',
message='Your application description page.',
photo_tags = photo_tags
)
My template is as follows:
{% extends "layout.html" %}
{% block content %}
<h2>{{ title }}.</h2>
<h3>{{ message }}</h3>
{% for phototag in photo_tags %}
<div style="float:left; class=" img-responsive">
<p>photo</p>
<p></p>tag</p>
<img src="static/photos/{{ phototag.id }}" width="100" height="100">
</div>
{% endfor %}
{% endblock %}
I am pretty sure the models and association table/model are setup properly.
The template is not perfect, as it currently appears to show tag ids for photo ids. I have tried to do 'phototag.photo_id' or 'phototag.filename' but doesn't come out. Obviously view query is not putting that through.
So the view is what i need help with. Is the query correct? and is it getting url passed parameter for photo_id correctly?
My test data is simple. I have a single Photo record with photos.id = 1
This has 2 related Phototags records: phototags.id = 1 (tag.id = 1), phototags.id = 2 (tag.id = 2)
When I pass url http://localhost:5555/phototags/1 my view query passes tag ids, but changing the passed parameter always gets the same tag ids eg phototags/2 also gets the same two tags. So query is obviously not correct.
I have looked at scores of examples and they all subtly different than what I want. None of the examples/tutorials/SO questions/answers i have seen show how the model, view and template work together to get what I want. They are either:
getting opposite eg equivalent of photos by tag (want tags by photo)
are just query that gets the tags by photo (i don't even think i am getting that)
have another SQLalchemy notation that includes 'sessions' or 'base' instead of 'db.model'
What I want as output is a photo id so i can show photo and its name etc and also show a list of tags associated with that photo eg as a comma separated list.
I am stumped to find a demo/example/tutorial/github project that walks me through what i need for workflow.
Can anyone show me example of view that can get photo id from url parameter and then query my models to get the associated tags?
It seems more appropriate to query a photo instead of photo_tags from what you describe about your use case.
With the view function
#app.route('/phototags/<int:id>')
def phototags(id=None):
photo = Photo.query.get(id)
return render_template(
'phototags.html',
title='PhotoTags',
message='Your application description page.',
photo = photo
)
you can then display the photo and iterate its tags using the 'tags' relationship in the html template:
{% extends "layout.html" %}
{% block content %}
<h2>{{ title }}.</h2>
<h3>{{ message }}</h3>
<img src="static/photos/{{ photo.id }}" width="100" height="100">
{% for phototag in photo.tags %}
<div style="float:left; class=" img-responsive">
<p>photo</p>
<p></p>tag</p>
</div>
{% endfor %}
{% endblock %}
Note that I used the get function in the query for the Photo. It's basically the same as
Photo.query.filter(id == id).first()
Renaming the view function and the template from phototags to photo would also make sense.
If you wanted to display all images for a tag you have to reverse the logic, querying for a tag and iterating over the photos. Should be possible, because you defined a backref.

Django - Admin custom field display & behavior

Let's imagine this model:
class ScribPart(models.Model):
name = models.CharField(max_length=50, unique=True)
text = models.TextField()
I'd like to attach a specific class to the field text and call a specific js file. So that the admin page would be like:
...
<script type="text/javascript" src="/static/js/mymarkup.js"></script>
...
<textarea id="id_text" name="text" class="mymarkup"></textarea>
...
How can I do that with a widget and/or custom admin form ?
To insert a <script> in an admin page the simplest thing to do is:
class ScribPartAdmin(model.ModelAdmin):
...
your normal stuff...
...
class Media:
js = ('/path/to/your/file.js',)
ModelAdmin media definitions documentation
Now to add the class attribute to the textarea I think the simplest way to do it is like this:
from django import forms
class ScribPartAdmin(model.ModelAdmin):
...
your normal stuff...
...
class Meta:
widgets = {'text': forms.Textarea(attrs={'class': 'mymarkup'})}
Overriding the default widgets documentation
I should add that this approach is good for a one shot use. If you want to reuse your field or JS many times, there's better ways to do it (custom widget for the field, with JS file specified if the JS is exclusively related to the field, extending template to include a JS file at many places).
You have to create a template, put it in templates/admin/change_form_scribpart.html with this content:
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block content %}
<script type="text/javascript" src="/static/js/mymarkup.js"></script>
{{ block.super }}
{% endblock %}
Also, don't forget to activate this new admin template in your ScribPart ModelAdmin:
class ScribPartAdmin(admin.ModelAdmin):
ordering = ...
fieldsets = ...
change_form_template = "admin/change_form_scribpart.html"
You can send your form with json pack and get(check) with this code
results = ScribPart.all()
for r in results :
if r.test == id_text:
self.response.out.write("<script type='text/javascript' src='/static/js/"+r.name+"mymarkup.js'></script>")

Categories

Resources