Plugin with editable link element - django

While implementing a Django CMS site, I’m a little stuck on link management (internal or external). In my project I have a specific box plugin the operator is to use quite often. I added screenshots of edit dialog and box rendering at the end of the question.
The edit dialog is nice, but right now the button is just a char field. So the link selection, either to a page within Django CMS or to an external URL, is missing. I looked for a link field, but until now I am lost.
How to add the feature to let the operator select an internal or external link ?
The plugin consists of these parts:
models.py
from django.db import models
from cms.models.pluginmodel import CMSPlugin
from djangocms_text_ckeditor.fields import HTMLField
class CardPlugin(CMSPlugin):
title = models.CharField(max_length=256,default='')
description = HTMLField(configuration='CKEDITOR_SETTINGS',
default='')
button = models.CharField(max_length=256,default='')
def __str__(self):
return str(self.title)
cms_plugins.py
class CardCMSPlugin(CMSPluginBase):
model = CardPlugin
name = 'Card'
render_template = "card-default.html"
card-default.html
{% load cms_tags %}
<section class="card card--primary-light">
<div class="card__inner">
<div class="card__content">
<div class="card__text">
<h2 class="card__title">
{{ instance.title }}
</h2>
<p class="card__description">
{{ instance.description }}
</p>
</div>
{% if instance.button %}
<div class="card__buttons">
{{ instance.button }}
</div>
{% endif %}
</div>
</div>
</section>
the rendered box
The plugin edit dialog looks like this:

I'd suggest looking at adding the djangocms-link plugin as a child plugin. It's a very good plugin to link to internal CMS pages or external addresses. That way you could drop the button field from your model, and instead render the child plugins in your template.
The docs on nested plugins would be a good read.
Your plugin definition would become something like this;
class ParentCMSPlugin(CMSPluginBase):
render_template = 'parent.html'
name = 'Parent'
model = ParentPlugin
allow_children = True
child_classes = ['LinkPlugin']
To render child plugins you'd then do this with your template;
{% load cms_tags %}
<section class="card card--primary-light">
<div class="card__inner">
<div class="card__content">
<div class="card__text">
<h2 class="card__title">
{{ instance.title }}
</h2>
<p class="card__description">
{{ instance.description }}
</p>
</div>
{% for plugin in instance.child_plugin_instances %}
{% render_plugin plugin %}
{% endfor %}
</div>
</div>
</section>
And that would use the default render template for the child plugin. If the default didn't match the styling etc, you could handle the rendering in the template instead of using render_plugin or subclass the LinkPlugin to work how you want, or extend it's attributes etc.
Some further consideration should do to dropping your description field in favour of also using the TextPlugin as a child, because the CMS text plugin can nest plugins within itself and is something I'd always use over an HTMLField.
Further still, if you're developing applications hooked in to CMS, take a look at PlaceholderFields which allow you to create placeholders in your own models to hold & use the CMS plugins that you can use in CMS pages. That gets really good for things like news apps or blog style content etc.

Related

External URL into a iframe to embed an external url within Django

I would like to embed a pptx that is uploaded into a folder in OneDrive within a iframe tag in a Django template. I have the urls stored in a model and saved into the SQLite database. In this sense, in the views.py file, I have the following code:
context = {
'selectedunit': selectedunit,
'url_to_be_inserted': MyModel.objects.filter(unit=selectedunit)
}
return render(request, 'web.html', context)
The code for web.html is very easy:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="container col-lg-8">
<div class="center">
<iframe class="center" src={{ url_to_be_inserted.url }} width="100%" height="300%" frameborder="0"/>
</div>
</div>
{% endblock %}
The result is the snapshot below:
While, I would like to embed the ppt into the web site. If I directly insert the URL, instead of using the context variable, it works. That is to say:
<iframe class="center" src="https://..." width="100%" height="300%" frameborder="0"/>
In this case, the result is as follows (ppt embedded into the Web site):
The reason why doing in this sense is because, depending on the selectedunit variable, I would like to address a different pptx with a different URL and I would like to dynamically change the pointer (as you see above by filtering the model).
How could I solve it?
Many thanks in advance

Data base saving & Redirection issue using django

I have an issue, I do not know why it is happening and how to solve it;
My app ask a user to create a project and is redirect directly to the project detail page. On that detail page if a team_id is empty I ask the user to create a team and when the team is created the user is redirected again to the project detail page to now be able to populate his team.
I used the code {% if Project.team_id == None %} when the user is redirected after creating his team but it is not working .. could you please help ? It is like before the redirection the new team is not saved in the Db ..
my html:
{% extends 'base.html' %}
{% block body %}
<div class="container">
<div class="jumbotron">
<h2>Welcome to your Project {{ project.name }} Detail page</h2>
</div>
{% if Project.team_id == None %}
<div class="invite-team">
<div class="jumbotron">
<div class="jumbo-text">
<h3>It is time to link a team to your project now create a new team and add team members</h3>
</div>
<div class="jumbo-button">
<span class="glyphicon glyphicon-plus"></span> Create a new team
</div>
</div>
{% else %}
<div class="invite-teammembers">
<div class="jumbotron">
<div class="jumbo-text">
<h3>The team {{ project.team_id }} has beed created, we now need to add TeamMembers</h3>
</div>
<div class="jumbo-button">
<span class="glyphicon glyphicon-plus"></span> Create a new team
</div>
</div>
</div>
{% endif %}
</div>
</div>
{% endblock%}
Looking at your surrounding code, you are using project as the container of your project. However, in your statement you are using Project (first character uppercase). Changing Project to project might help.
Your comment question:
what do you mean "Looking at your surrounding code, you are using project as the container of your project". my model Project is with a capital letter why now it is without ?
With looking at the surrounding code I mean that I literally looked at your code how you are using the variables in the other parts of your code. I am not sure if you are using CBV (class based views) or FBV (function based views).
With CBV the object is added to the context with the name defined in:
DetailView:81
or ListView:104
You can override the context object name by using the context_object_name in the View class
If you are using FBV, you have added it to the context manually as something like:
return render(request, 'myapp/template.html', {
'project': <project_query_or_variable>,
})

Django and tabbed navigationin templates

I am building a django project which among others has a customer model. Any customer can be a foreign key to some calendar entry models or some picture models. I want to be able to get in to a customers page (e.g domain/customoer/1) and be able to navigate to the different models the customer is related with (e.g all the pictures for the customer, all the calendar entries of the customer). I am using bootstrap for the "presentation of the site. My idea was to use tabs. So I created a pil for my main template the customer.html
<ul class="nav nav-pills">
<li class="active">Personal Data</li>
<li>History</li>
<li>Analysis</li>
<li>Diagnosis</li>
<li>Treatment</li>
<li>Appointments</li>
<li>Graphics</li>
</ul>
and i was thinking of including a template for each pill
<div class="tab-content">
<div id="personal-data" class="tab-pane active ">
<div id="history" class="tab-pane">History is in the making</div>
<div id="analysis" class="tab-pane">
{% include 'customer/analysis.html' with customer=customer %}
</div>
<div id="diagnosis" class="tab-pane">Diagnosis is differential</div>
<div id="treatment" class="tab-pane">Treatment what treatment??</div>
<div id="appointments" class="tab-pane">Ap point ment</div>
<div id="graphics" class="tab-pane">Now this is going to be hard!</div>
The templates in each tab can do different things like upload pics navigate to different pages etc.
When i hit on a pill the url (domain/customer/1/) won't change (naturally) to inform me to which tab i am at the moment. So my question is how can i know in which tab i am ath the moment? I want the user to be able to do different things from different tabs (upload pics etc) and I want to be able to redirect to the specific tab after the view is called? Maybe #id could be appended to the url to specify the tab, but it doesn't happen with bootstrap.
What is the best way to deal with tabs in django? Ajax maybe? Will I not have the same problem? Any ideas or lings would be nice too
I use template inheritance for this kind of thing. It's simple and flexible. For example, you can define your main navigation in your base template like so:
...
<li {% block news %}{% endblock %}>News</li>
<li {% block features %}{% endblock %}>Features</li>
<li {% block sport %}{% endblock %}>Sport</li>
...
Then, in your base templates for each of those apps you'd have something like:
<!-- news/base_news.html -->
{% extends 'base.html' %}
...
{% block news %}class="active"{% endblock %}
...

Template Django application extending template django project

I am quite a beginner in django and I need some advices.
I am trying as much as possible to create reusable django applications that will be used in several different projects. But I don't know how to proceed with templates.
If I have an application managing user, I think the template allowing to add, remove or list a user shall be located in the application and not in the project. Templates project should define headers, footers and general organisation (correct me if I'm wrong).
However, if I want to use template inheritance I will extend project template in my application template :
{% extends "base.html" %}
{% block content %}
...
{% endblock %}
So in developping my reusable application I make the assumption that my project will have a template called base.html with a block content, and in my mind this information should not be located at application level, but in project level. In some projects I will want to display users in block content, but not necessarily in others. I could want to display user information in several places in the same page for example...
How do you developp your application template to bypass this limitation ?
Thanks in advance,
Bill
What you are describing is probably best solved with custom template tags, specifically inclusion tags.
I would do a basic html template containing a header and a footer, and many reusable templates extending the basic one, containing the different layouts I would need. I would also create reusable components (tiles, datagrids...).
For the templates :
base.html
<!doctype HTML>
<html>
<head>
....
</head>
<body>
{% block content %}
</body>
</html>
3_columns.html
{% extends "project/base.html" %}
{% block content %}
<div class="line">
<div class="column">{% block col1 %}</div>
<div class="column">{% block col2 %}</div>
<div class="column">{% block col3 %}</div>
</div>
{% endblock %}
2_lines.html
{% extends "project/base.html" %}
{% block content %}
<div class="line">{% block line1 %}</div>
<div class="line">{% block line2 %}</div>
{% endblock %}
A basic custom component :
templatetags/custom.py
import django
from django.template.defaulttags import register
#register.inclusion_tag('components/custom.html')
def custom(params):
context = {
'a': params['a'],
'b': params['b']
}
return context
templates/components/custom.html
<div class="custom">
<label>{{ a }}
<input name={{ b }}
</label>
</div>
django-admin.py collectstatic
Read docs
Files are searched by using the enabled finders. The default is to look in all locations defined in STATICFILES_DIRS and in the 'static' directory of apps specified by the INSTALLED_APPS setting.

Can't Embed YouTube Link Within Django Template Tag, Twitter Bootstrap

I'm currently attempting to embed a user-submitted YouTube link via a Django form within a Twitter Bootstrap layout.
The space for the video is appearing and the source code reflects the correct information and link, but neither the video nor the player appears. I'm also using the "flex-video" class from this link for a responsive layout http://poslavsky.com/blog/2012/04/01/responsive-video-in-twitter-bootstrap/ but it doesn't work when that class is changed to another name such as "video" either.
This is the code:
<div class="row">
<div class="span12">
<span>{{story.author}}</span><br>
<span>{{story.zip_code}}</span><br>
<span>{{story.date}}</span><br>
<p>{{story.copy}}</p>
<div class="image">
{% if story.pic %}
<img src="{{ story.pic.url }}" alt="some_image_alt_text" />
{% endif %}
</div>
<div class="flex-video">
{% if story.video %}
<p> <iframe width="460" height="250" src="{{ story.video}}" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
</p>
{% endif %}
</div>
</div>
Any insight greatly appreciated.
I guess {{story.video}} gives Youtube video Url something similar to this http://youtube.com/watch?v=ASO_ypdnsQ which is direct youtube url, and not embed url.
Embed URL for same video is different than direct url, like this http://youtube.com/embed/....
I created a custom template tag, here is how.
import urlparse
...
#register.inclusion_tag('video_embed.html', takes_context=True)
def youtube_embed(context, url):
url_data = urlparse.urlparse(url)
query = urlparse.parse_qs(url_data.query)
video_id = query["v"][0]
context['embed_url'] = ('http://youtube.com/embed/%s' % video_id)
return context
Then, in templates just load the tag, and pass the youtube url. It will give embed url from normal url.