Recreating bootstrap cards row layout with tailwind in django - django

ASK
I'm trying to recreate bootstrap cards row layout with Tailwind within django framework
BLOCKER
However the tailwind attempt results in below
index.html -- bootstrap
{% extends 'base.html' %}
{% block title %}Home{% endblock title %}
{% block content %}
<div class="py-2">
<div class="row">
{% for t in object_list %}
<div class="col-md-3">
<div class="card mb-4 box-shadow bg-green-500">
<div class="card-body">
<h2 style="font-size:18px;font-weight:bold;min-height:42px;"><a class="text-dark" href="#">
{{t.currency|truncatechars:50}}</a></h2>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">{{t.country|truncatechars:25}}</small>
</div>
</div>
</div>
</a>
</div>
{% endfor %}
</div>
{% endblock content %}
index.html -- tailwind
{% extends 'base.html' %}
{% block title %}Home{% endblock title %}
{% block content %}
<div class="p-10 ">
<div class="max-w-sm rounded overflow-hidden shadow-lg">
{% for t in object_list %}
<div class="px-6 py-4">
<div class="font-bold text-xl mb-2">{{t.country}}</div>
<p class="text-gray-700 text-base">
{{ t.currency }}
</p>
</div>
{% endfor %}
</div>
</div>
{% endblock content %}

You're starting the for loop a tag too late on the Tailwind version so all of your items are in a single card. And to recreate a 4 column grid layout in Tailwind I recommend using the grid utilities, specifically grid which is display: grid and grid-cols-4 which is grid-template-columns: repeat(4, minmax(0, 1fr)).
Your code might look like this:
{% extends 'base.html' %}
{% block title %}Home{% endblock title %}
{% block content %}
<div class="p-10 grid sm:grid-cols-2 md:grid-cols-4 gap-5">
{% for t in object_list %}
<div class="bg-green-500 rounded overflow-hidden shadow-lg">
<div class="px-6 py-4">
<div class="font-bold text-xl mb-2">{{t.country}}</div>
<p class="text-gray-700 text-base">
{{ t.currency }}
</p>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
Here's a visual of what the expected output would be https://play.tailwindcss.com/AWK45UcOug

Related

Login in django failing after adding css to login page

I have a basic django website running on a postgres database.
The login page code was structured as follows,
{% extends "_base.html" %}
{% load crispy_forms_tags %}
{% block title %}Log In{% endblock title %}
{% block content %}
<h2>Log In</h2>
<div class="container text-center">
<div class="row justify-content-center">
<div class="col-4">
<form method="post">
{% csrf_token %}
{{ form | crispy }}
<button class="btn btn-primary " type="submit">Log In</button>
</form>
</div>
</div>
</div>
{% endblock content %}
and _base.html as
<!-- additional css content for navbar -->
<div class="container-fluid full-height p-0">
{% block content %}
{% endblock content %}
<!-- similar footer content -->
And then I decided to add some css from the bootstrap in the form of a just so my login page would look cleaner. Therefore I added some css in this form.
{% extends "_base.html" %}
{% load crispy_forms_tags %}
{% block title %}Log In{% endblock title %}
{% block content %}
<div class="bg-dark vh-100 d-flex align-items-center justify-content-center">
<div class="col-3 p-5 border bg-light rounded-2">
<h2>Log In</h2>
<form method=" post">
{% csrf_token %}
{{ form | crispy }}
<button class="btn btn-primary " type="submit">Log In</button>
</form>
</div>
</div>
{% endblock content %}
with _base.html as follows
<div class="container-fluid p-0">
{% block content %}
{% endblock content %}
</div>
As you can see my I haven't touched the form "component". Why is the form not working?
Note: I have configured my static files properly, i.e directories mentioned in settings.py
I had setup to redirect to the home page, but the link that is getting passed in to the url is:
http://localhost:8000/accounts/login/?csrfmiddlewaretoken=XgEmrXg1fMJfOoPSnDyuY733MrWTxjaAWHnCnej9sFI6buue93sMgggrwIsTOibd&login=adminsav%40email.com&password=testpass123

Can't see removal flags

Django 3.0.8
django-comments-xtd==2.6.2
I'm studyint this section of the tutorial:
https://django-comments-xtd.readthedocs.io/en/latest/tutorial.html#removal-suggestion
post_detail.html
{% extends "base.html" %}
{% load comments %}
{% load comments_xtd %}
{% block title %}{{ object.title }}{% endblock %}
{% block content %}
<div class="pb-3">
<h1 class="text-center">{{ object.title }}</h1>
<p class="small text-center">{{ object.publish|date:"l, j F Y" }}</p>
</div>
<div>
{{ object.body|linebreaks }}
</div>
{% get_comment_count for object as comment_count %}
<div class="py-4 text-center">
Back to the post list
⋅
{{ comment_count }} comment{{ comment_count|pluralize }}
ha{{ comment_count|pluralize:"s,ve" }} been posted.
</div>
{% if object.allow_comments %}
<div class="card card-block mb-5">
<div class="card-body">
<h4 class="card-title text-center pb-3">Post your comment</h4>
{% render_comment_form for object %}
</div>
</div>
{% endif %}
{% if comment_count %}
<ul class="media-list">
{% render_xtdcomment_tree for object allow_flagging allow_feedback %}
</ul>
{% endif %}
{% endblock %}
settings.py
COMMENTS_XTD_APP_MODEL_OPTIONS = {
'blog.post': {
'allow_flagging': True,
'allow_feedback': False,
'show_feedback': False,
}
}
Full code at Github: https://github.com/Kifsif/comments
Problem
I have loged in. But I can't see any flag at the right side of every comment’s header.
Could you give me a hint where the problem may be hiding?
I think you will have to import the font awesome stylesheet:
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">

Jinja2: Create new row for every 3 items

Currently for every article in articles a new div with class span4 is created.
Instead for each row I would like to limit it's content to three span's and create a new row once that limit has been reached. How can I best implement this?
{% extends "base.html" %}
{% block content %}
<div class="container-fluid">
<legend></legend>
<div class="row-fluid" id="main">
{% for article in articles %}
<div class="span4">
<div class="thumbnail">
<img src="http://placehold.it/300x150/483CB4">
<div class="caption">
<h4>{{ article.title }}</h4>
<p> {{ article.summary }}</p>
</div>
<legend></legend>
<a class="btn" href="#"><i class="icon-thumbs-up"></i></a>
<a class="btn" href="#"><i class="icon-thumbs-down"></i></a>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
Goal:
<div class="row">
<div class="span4">article[0]</div>
<div class="span4">article[1]</div>
<div class="span4">article[2]</div>
</div>
<div class="row">
<div class="span4">article[3]</div>
<div class="span4">article[4]</div>
<div class="span4">article[5]</div>
</div>
The best way to do this is to use the built in batch filter to break up your list into groups of three:
{% for article_row in articles | batch(3, ' ') %}
<div class="row">
{% for article in article_row %}
<div class="span4">{{ article }}</div>
{% endfor %}
</div>
{% endfor %}
You can use loop.index0 and loop.last inside the for loop. Here is the for-loop documentation.
Example:
{% extends "base.html" %}
{% block content %}
<div class="container-fluid">
<legend></legend>
<div class="row-fluid" id="main">
{% for article in articles %}
{% if loop.index0 % 3 == 0 %}
<div class="row">
{% endif %}
<div class="span4">
...
</div>
{% if loop.index0 % 3 == 2 or loop.last %}
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endblock %}
The loop.last clause should close the last row even if there were less than 3 items. <div> should start when loop.index0 gives 0 as the remainder and should end when 2 is the remainder
Another alternative would be to group the items into rows before passing them into the template, then you can just issue two for-loops one inside the other.

Django, Template

I am beginner of Django and Template language...
Here is my code:
base.html
{% block news%}
<div class="row">
<div class="span6">
<div class="news-content clearfix">
<div class="news-title">Манай хамт олны тухай</div>
<div class="text clearfix>
<img src="{{STATIC_URL}}img/image1.jpg">
# here is some text
</div>
<div class="pull-right">00
<a class="btn btn-small" href="#">Дэлгэрэнгүй</a>
</div>
</div>
</div>
<div class="span6">
<div class="news-content clearfix">
<div class="news-title">#title</div>
<div class="text clearfix">
<img src="{{STATIC_URL}}img/image2.jpg">
# text-2
</div>
<div class="pull-right">
<a class="btn btn-small" href="#">Дэлгэрэнгүй</a>
{% endblock %}
news_list.html
{% extends "base.hmtl"%}
{% block news %}
{% for news in news_list %}
######## here i want to display last 2 news at row #########
{% endfor %}
{% endblock %}
You are getting it all wrong.
The base.html must contain all the code that is to be reused over your website.For example the files like CSS and javascript are included in the base.html
Inside the base.html you are to include a block that is to hold the code that varies from page to page.You can use multiple blocks as well,like header,body, and footer.
When a template is rendered,the requested template "imports" the base.html using {% extends "base.html" %}.After the import,the block defined in the base.html is replace by the block in the requested template.
As per your question,the code you have written in the base.html that defines how to display your news is to come under the news_list.html,under the for loop.
I assume that the news_list is a QuerySet ie a result of a database query and contains the attributes title,content etc
{% extends "base.html" %}
{% block news %}
{% for news in news_list %}
<div class="row">
<div class="span6">
<div class="news-content clearfix">
<div class="news-title">{{ news.title }}</div>
<div class="text clearfix>
<img src="{{STATIC_URL}}img/image1.jpg">
</div>
<div class="pull-right">00
<a class="btn btn-small" href="#">{{ whatever }}</a>
</div>
</div>
</div>
{% endfor %}
{% endblock %}
And your base.html
<html>
CSS,JS here if any
<body>
{% block news %}
{% endblock %}
</body>
</html>

Django template include a template with a variable coming from view

I have problem with Django templates. I want to create a base html, which I will use to display posts. I call a template from view, which includes an html file, where the file extends the base html.
view
def main(request):
all_posts = News.objects.all()
return render_to_response("index.html", {'all_posts': all_posts})
template -- index.html
<div id="content">
{% include 'content.html' with posts=all_posts%}
</div>
content.html
{% extends "content_base.html" %}
{% for post in posts %}
{% block date_of_post %} {{ post.date }} {% endblock %}
{% block post_author %} {{ post.author }} {% endblock %}
{% block post %} {{ post.content }} {% endblock %}
{% endfor %}
content_base.html
<div class="post">
<h2 class="title">{% block blabla %}{% endblock %}</h2>
<p class="meta"><span class="date">{% block date_of_post %}{% endblock %}</span><span class="posted">Posted by {% block post_author %}{% endblock %}</span></p>
<div style="clear: both;"> </div>
<div class="entry">
<p>
{% block post %} {% endblock %}
</p>
<p class="links">
Read More
Comments
</p>
</div>
</div>
But it seems like I cannot pass the *all_posts* variable to content.html. What is the problem here? Am I doing something wrong?
Thanks in advance.
You should move the loop into index.html, and include content_base.html directly. So index.html becomes:
<div id="content">
{% for post in posts %}
{% include 'content_base.html' %}
{% endfor %}
</div>
and content_base.html is
<div class="post">
<h2 class="title">{{ post.title }}</h2>
<p class="meta"><span class="date">{{ post.date }}</span><span class="posted">Posted by {{{ post.author }}</span></p>
<div style="clear: both;"> </div>
<div class="entry">
<p>
{{ post.content }}
</p>
<p class="links">
Read More
Comments
</p>
</div>
</div>
You're using blocks with identical names, because you're using them in a loop:
{% for post in posts %}
{% block date_of_post %} {{ post.date }} {% endblock %}
{% block post_author %} {{ post.author }} {% endblock %}
{% block post %} {{ post.content }} {% endblock %}
{% endfor %}
You can't do that. Look here.
Sometimes too much normalization is not so good. You can simply have index.html and all of your code can go there (avoiding unnecessary blocks).
<div id="content">
{% for post in all_posts %}
<div class="post">
<h2 class="title">{{post.title}}</h2>
<p class="meta"><span class="date">{{post.date}}</span><span class="posted">Posted by {{post.post_author}}</span></p>
<div style="clear: both;"> </div>
<div class="entry">
<p>
{{post.content}}
</p>
<p class="links">
Read More
Comments
</p>
</div>
</div>
{% endfor %}
</div>