I'm using bootstrap to implement my post detail page.
It works well and fit perfectly into tho format when using Korean.
But, if I wrote english contents, it overflow the format.
What's wrong with it?
Here is the code :
models.py
from django.db import models
from django.core.urlresolvers import reverse
from django.conf import settings
def upload_location(instance, file_name):
return "{}/{}".format(instance.author.username, file_name)
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
content = models.TextField()
image = models.ImageField(upload_to=upload_location, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('-created_at',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse(
"posts:detail",
kwargs={
"pk": self.id,
}
)
def get_image_url(self):
if self.image:
return self.image.url
return "http://placehold.it/300x200"
post_detail.html
{% extends 'chacha_dabang/skeleton/base.html' %}
{% load pipeline %}
{% block content %}
<div class="container">
<section class="post-content-section">
<h2> {{ post.title }} </h2>
<h5 style="text-align: right;"> {{ post.created_at }} </h5>
<hr class="thin">
<img src="{{ post.get_image_url }}" alt="image">
<p> {{ post.content }} </p>
</section>
</br>
<hr class="thin">
</br>
<section id="comment-section" data-post-id={{ post.pk }}>
<h3> 댓 글 (<span id="comment-count"></span>)</h3>
<ul>
</ul>
<form method="POST" action="">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</section>
</div>
{% endblock %}
{% block custom_js %}
{% javascript "comments" %}
{% javascript "message" %}
{% endblock %}
Related
My Problems are as follows:
Im relatively new to Django. so sorry for this mess.
I've tried to implement threaded comments to my blog via MPTT. But when i pressing the 'Reply' Button django throws me a Type Error
Normal parent comments working correctly
When i just create a comment with via the admin site, i can create parent comments and child comments and they will be indented just as expected in the main Application too...
my Database is mySQL.
The Error:
in _calculate_inter_tree_move_values
space_target = target_right - 1
~~~~~~~~~~~~~^~~
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'
my models.py:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from mptt.models import MPTTModel, TreeForeignKey
STATUS = (
(0,"Draft"),
(1,"Publish")
)
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete= models.CASCADE, related_name='blog_posts')
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post_detail',args=[self.slug])
class Comment(MPTTModel):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=False)
parent=TreeForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, related_name='children')
class MPTTMeta:
order_insertion_by = ['created_on',]
def __str__(self):
return 'Comment {} by {}'.format(self.body, self.name)
#just for the threaded comments
def get_comments(self):
return Comment.objects.filter(parent=self).filter(active=True)
views.py:
from django.shortcuts import render, get_object_or_404, redirect, HttpResponseRedirect
from django.views import generic
#from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
#from django.template import loader
from .models import Post, Comment
from .forms import CommentForm
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'index.html'
paginate_by = 3
#class PostDetail(generic.DetailView):
# model = Post
# template_name = 'post_detail.html'
class AboutMe(generic.TemplateView):
template_name = 'about_me.html'
class Contact(generic.TemplateView):
template_name = 'contact.html'
class Impressum(generic.TemplateView):
template_name = 'impressum.html'
class StaticContent(generic.TemplateView):
template_name = 'static_html_content.html'
class SideBar(generic.TemplateView):
template_name = 'sidebar.html'
#class PostDetail(generic.DetailView):
# model = Post
# context_object_name = "post"
# template_name = "post_detail.hhml"
def post_detail(request, post):
template_name = 'post_detail.html'
post = get_object_or_404(Post, slug=post, status=1)
comments = post.comments.filter(active=True)
new_comment = None
#comment posted
if request.method == 'POST':
comment_form = CommentForm(request.POST)
if comment_form.is_valid():
# Create comment object but dont save to database yet
new_comment = comment_form.save(commit=False)
# Assign thecurrent post to the comment
new_comment.post = post
#save the comment to the database
new_comment.save()
#redirect to the same page and focus on that comment
return HttpResponseRedirect('/' + post.slug)
#return redirect(post.get_absolute_url()+'#'+str(new_comment.id))
else:
comment_form = CommentForm()
return render(request, template_name, {'post': post, 'comments': comments, 'new_comment': new_comment, 'comment_form': comment_form})
def reply_page(request):
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
post_id = request.POST.get('post_id')
parent_id = request.POST.get('parent')
post_url = request.POST.get('post_url')
print(post_id)
print(parent_id)
print(post_url)
print('was here reply!')
reply = form.save(commit=False)
reply.post = Post(id=post_id)
reply.parent = Comment(id=parent_id)
reply.save()
return redirect(post_url+'#'+str(reply.id))
return redirect('/')
forms.py:
from .models import Comment
from django import forms
from mptt.forms import TreeNodeChoiceField
class CommentForm(forms.ModelForm):
parent = TreeNodeChoiceField(queryset=Comment.objects.all())
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['parent'].widget.attrs.update(
{'class': 'd-none'})
self.fields['parent'].label = ''
self.fields['parent'].required = False
class Meta():
model = Comment
fields = ('name', 'parent', 'email', 'body')
widgets = {
'name': forms.TextInput(attrs={'class': 'col-sm-12'}),
'email': forms.TextInput(attrs={'class': 'col-sm-12'}),
'body': forms.Textarea(attrs={'class': 'form-control'}),
}
def save(self, *args, **kwargs):
Comment.objects.rebuild()
return super(CommentForm, self).save(*args, **kwargs)
post_details.html:
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% load mptt_tags%}
{% block content %}
<header class="masthead" style="height: 13.9em;">
<!-- javascript add -->
<script src="{% static 'js/main.js'%}"></script>
</header>
<div class="container">
<div class="row">
<div class="col-md-8 card mb-4 mt-3 left top">
<div class="card-body">
<h1>{% block title %} {{ post.title }} {% endblock title %}</h1>
<p class=" text-muted">{{ post.author }} | {{ post.created_on }}</p>
<p class="card-text ">{{ post.content | safe }}</p><br>
<a href="{% url 'home' %}" style="float: right;"
class="btn btn-danger">Go Back</a><br><br>
</div>
</div>
{% block sidebar %} {% include 'sidebar.html' %} {% endblock sidebar %}
</div>
<div class="row">
<div class="col-md-8 card mb-4 mt-3 left top">
<div class="card-body">
<h3>Add Comment</h3>
<form method="POST" action="">
{% csrf_token %}
{{ comment_form | crispy }}
<button type="submit" class="btn btn-danger">Comment</button>
</form>
<!-- count comments section-->
{% with comments.count as total_comments %}
<h3 class="mt-5">
{{ total_comments }} comment{{ total_comments|pluralize }}
</h3>
{% endwith %}
<!-- show comment section -->
<div>
<ul style="list-style-type: none;">
{% recursetree comments %}
<li>
<!-- parent body -->
<div>
<div class="border p-4 rounded">
<h4>{{ node.name }}</h4>
<small class="text-muted">On {{ node.created_on }}</small>
<h5>{{ node.body }}</h5> <br>
<button class="btn btn-danger btn-sm" onclick="handleReply({{node.id}})">Reply</button>
<div id="reply-form-container-{{node.id}}" style="display:none">
<form method="POST" action="{% url 'reply' %}" class="mt-3">
{% csrf_token %}
<input type="hidden" name="post_id" value="{{post.id}}">
<input type="hidden" name="parent" value="{{comment.id}}">
<input type="hidden" name="post_url" value="{{post.get_absolute_url}}">
{{comment_form|crispy}}
<div>
<button type="button" onclick="handleCancel({{node.id}})" class="btn btn-danger border btn-sm">Cancel</button>
<button type="submit" class="btn btn-danger btn-sm">Submit</button>
</div>
</form>
</div>
</div>
</div>
<br>
<!-- if children -->
{% if not node.is_leaf_node %}
<ul ul style="list-style-type: none;">
<div class="children pl-2 pl-md-5">
{{ children }}
</div>
</ul>
{% endif %}
</li>
{% endrecursetree%}
</ul>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
I've tried to change the values in the formfields of the post_details.html to node.parent.id
but nothing seems to happen.
Also i tried to change the parent_id's datatype to see if there something happens.
but because it runs in this Opperant-Error i think it could be an issue with saving to the mySQL Database...
Ok... Now i have have found the answer.
In views.py i've edited these lines:
parent_id = request.POST.get('parent')
and replace 'parent' with 'commend_id'
parent_id = request.POST.get('comment_id')
In post_detail.html i have changed the form:
<input type="hidden" name="parent" value="{{comment.id}}">
to...
<input type="hidden" name="comment_id" value="{{node.id}}">
Now it runs as expected! YAY!
Hej!
I'm having trouble with my django filter.
When I put {{myFilter}} in the template I only get an ObjectNumber and when I put {{myFilter.form}} I get the error:
ValueError at /plants/plants/
too many values to unpack (expected 2)
Does anyone have an idea what's going on?
# views.py
def plants_view(request):
plants = Plant.objects.all()
myFilter = PlantFilter(plants)
context = {"plants": plants, "myFilter": myFilter}
return render(request, 'plants/search_table.html', context)
# filters.py
class PlantFilter(django_filters.FilterSet):
class Meta:
model = Plant
fields = ['name',]
it doesn't matter if I use fields = [ ] or fields = '__all__' .
template.html
{% extends "landing/base.html" %}
{% load static %}
{% load i18n %}
{% load admin_urls %}
{% block page-title %} {%translate "View Plants" %} {% endblock %}
{% block head %}
<link href="{% static 'landing/vendor/tabulator/dist/css/tabulator.min.css' %}" rel="stylesheet">
<link href="{% static 'landing/vendor/tabulator/dist/css/bootstrap/tabulator_bootstrap4.min.css' %}" rel="stylesheet">
{% endblock %}
{% block content %}
<br>
<div class="row">
<div class="col">
<div class="card card-body">
<form method="get">
{{myFilter.form}}
<button class="btn-primary" type="submit">Search</button>
</form>
</div>
</div>
</div>
</br>
# models.py
class Plant(models.Model):
name = models.CharField(
max_length=200
)
def __str__(self):
return f"{self.name}"
def serialize(self):
return {
"Name": self.name
}
Did you follow the documentation on this page ?
views.py
def plants_view(request):
plants = Plant.objects.all()
myFilter = PlantFilter(request.GET, queryset=plants)
context = {"plants": plants, "myFilter": myFilter}
return render(request, 'plants/search_table.html', context)
template.html
<form method="get">
{{ myFilter.form.as_p }}
<button class="btn-primary" type="submit">Search</button>
</form>
I made the comment section for my blog page, but the problem is it showing name and comment in a single line and I want both these in different lines. and \n is not working.
class comments(db.Model):
__tablename__ = 'comment'
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.Text)
comm = db.Column(db.Text)
def __init__(self,name,comm):
self.name = name
self.comm = comm
def __repr__(self):
return f" Name: {self.name} Comment: {self.comm}"
function
#app.route('/fat', methods=['GET','POST'])
def fat():
form = AddForm()
if form.validate_on_submit():
name = form.name.data
comm = form.comm.data
newname = comments(name,comm)
db.session.add(newname)
db.session.commit()
return redirect(url_for('fat'))
new = comments.query.all()
return render_template('fat.html',form=form, newnames=new)
the code for fat.html is attached below......................................................................................................................................................
</div>
{% block content %}
<div class="post comment">
{% for co in newnames %}
<li>{{co}}</li>
{% endfor %}
</div>
<div class="myform">
<h2>Leave a Comment</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div class="myforms">
<h1 class="myform1"> {{ form.name.label }}</h1>
<h1 class="myform2"> {{ form.name() }} </h1>
</div>
<div class="myformss">
<h1 class="myform3"> {{ form.comm.label }} </h1>
<h1 class="myform4"> {{ form.comm()}}</h1>
</div>
<div class="myformsss">
<h1 class="myform5"> {{ form.submit() }} </h1>
</div>
</form>
</div>
{% endblock %}
It's not that flexible to do the HTML content layout in the backend. The display style should be decided on the front end. I mean, you should modify your fat.html.
If you need my help. Modify your question and paste out the content of fat.html.
Update:
<div class="post comment">
{% for co in newnames %}
<li>Name: {{ co.name }}</li>
<li>Name: {{ co.comm }}</li>
{% endfor %}
</div>
Here's a simple example. You can access the Comment object just like what you do in Python.
You may need to change the css style to indent the comments block and make it align with the other blocks.
I am trying to implement a search feature with pagination.
I have successfully either managed to get the search to work or the pagination to work. But I cannot figure out how to get both of them working together at the same time.
Here is the .html, by switching object_list to filter.qs in the .html, I can switch between either searching correctly or pagination correctly.
Can someone help me fix the code so that I can have both working together ?
{% extends 'base.html' %}
{% load widget_tweaks %}
{% load my_tags %}
{% block head %}
<title> Overview</title>
{% endblock %}
{% block content %}
<form method="get">
<div class="jumbotron">
<h4 style="margin-top: 0">Filter</h4>
<div class="row">
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.name.label_tag }}
{% render_field filter.form.name class="form-control" %}
</div>
<div class="form-group col-sm-4 col-md-3">
{{ filter.form.city_location.label_tag }}
{% render_field filter.form.city_location class="form-control" %}
</div>
</div>
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</div>
</form>
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>City Location</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
<td>{{ object.name }}</td>
<td>{{ object.city_location }}</td>
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
</tbody>
</table>
<br>
<br>
<div id="footer">
<div class="container text-center">
<p class="text-muted credit" style="color:#fff">
{% if is_paginated %}
{% if page_obj.has_previous %}
First
{% if page_obj.previous_page_number != 1 %}
Previous
{% endif %}
{% endif %}
Page {{ page_obj.number }} of {{ paginator.num_pages }}
{% if page_obj.has_next %}
{% if page_obj.next_page_number != paginator.num_pages %}
Next
{% endif %}
Last
{% endif %}
<p>Objects {{ page_obj.start_index }}—{{ page_obj.end_index }}</p>
{% endif %}
</div>
</div>
{% endblock %}
Here is my models
from django.db import models
# Create your models here.
class lab(models.Model):
name = models.CharField(max_length=255)
city_location = models.CharField(max_length=255)
def __str__(self):
return self.Lab_name
Here is my views.py
class labListView(LoginRequiredMixin, ListView):
context_object_name = "Lab_folders"
model = lab
template_name = "researcher_view_app/Lab_overview.html"
paginate_by = 20
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = labOverviewFilter(self.request.GET, queryset=self.get_queryset())
return context
Here is my filters.py
import django_filters
class labOverviewFilter(django_filters.FilterSet):
Lab_name = django_filters.CharFilter(lookup_expr='icontains')
Lab_city_location = django_filters.CharFilter(lookup_expr='icontains')
And the part which I have no idea about, that I do not know how to modify but works is: my tempatetag
app_name/templatetags/my_tags.py
from django import template
register = template.Library()
#register.simple_tag(takes_context=True)
def param_replace(context, **kwargs):
"""
Return encoded URL parameters that are the same as the current
request's parameters, only with the specified GET parameters added or changed.
It also removes any empty parameters to keep things neat,
so you can remove a parm by setting it to ``""``.
For example, if you're on the page ``/things/?with_frosting=true&page=5``,
then
Page 3
would expand to
Page 3
Based on
https://stackoverflow.com/questions/22734695/next-and-before-links-for-a-django-paginated-query/22735278#22735278
"""
d = context['request'].GET.copy()
for k, v in kwargs.items():
d[k] = v
for k in [k for k, v in d.items() if not v]:
del d[k]
return d.urlencode()
You can apply filter in get_queryset method. Like this
class labListView(ListView):
context_object_name = "Lab_folders"
model = lab
template_name = "researcher_view_app/Lab_overview.html"
paginate_by = 20
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = labOverviewFilter(self.request.GET, queryset=self.get_queryset())
return context
def get_queryset(self):
qs = super().get_queryset()
word = labOverviewFilter(self.request.GET, queryset=qs)
return word.qs
pagination logic works after getting queryset. So provide filtered queryset to paginator.
I made a small blog site and is not showing all the items from the database. If i try to see the posts from my phone i see only 3 posts, when in my DB there are 9. When i click on one post i got a Not Found error saying that the requested URL posts/legea etc was not found on server.
LE: My server is inside a VM. Is this maybe an issue?
This is the link that should have all of the posts: http://cohen.ro/posts/
PS I dont have a migrations folder. I just created now and put an init.py file in it. Bu still after running migrate didn't see the migrations and the result is the same.
However, if i enter in admin trhourgh site/admin i can see all of the posts in DB and when i go back to the site all of the items are out there and i can read the posts.
Can someone, please help me in order to fix this?! thank you!
My post List:
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block head_title %} Blog | {% endblock %}
{% block content %}
<div class="container-fluid" style="width:91%;color: currentColor;!important;">
<div class="row" id="list_posts" style="background-color: white;padding-top: 40px;">
<br/>
<br/>
<br>
{% for obj in object_list %}
<div class="col-sm-4">
<div class="thumbnail">
{% if obj.image %}
<img src="{{ obj.image.url }}"/>
{% endif %}
<div class="caption" style="color:currentColor">
{% if obj.draft %} <h3>Staff Only Draft</h3> {% endif %}{% if obj.publish > today %}<h3>Staff Only: Future Post{%endif%}</h3>
<h2><a href='{{ obj.get_absolute_url }}' >{{obj.title }}</a> </h2>
<h5>{{obj.location }} </h5>
{% if obj.user.get_full_name %}<p>Author: {{ obj.user.get_full_name }}</p>{% endif %}
<p> {{ obj.content |linebreaks |truncatechars:150}}</p>
{# <p>View</p>#}
</div>
</div>
</div>
{# {% cycle "" "" "<div class='col-sm-12'><hr/></div></div><div class='row'style='background-color:white;color:currentColor'>" %}#}
{% cycle "" "" "<div class='col-sm-12'><hr/><br/></div><div class='row'style='background-color:white;color:currentColor'></div>" %}
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if object_list.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ object_list.number }} of {{ object_list.paginator.num_pages }}.
</span>
{% if object_list.has_next %}
next
last »
{% endif %}
</span>
</div>
</div>
</div>
Post Form:
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block head_title %} Blog | {% endblock %}
{% block content %}
<div class="container-fluid" id="post_form_id" style="background-color: teal">
<div class="col-sm-6 offset-sm-3">
<h1> Form </h1>
<form method='POST' action='' enctype="multipart/form-data"> {% csrf_token %}
{{ form |crispy }}
<input type="submit" class="btn btn-default" role="button" value="Create Post">
</form>
</div>
</div>
{% include 'navbar_bottom.html' %}
{% endblock %}
My Post detail:
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load i18n %}
{% block head_title %} Blog | {% endblock %}
{% block content %}
<div class="container-fluid" id="detail_posts" style="background-color: white">
<div class="col-xs-12 offset-xs-0 col-sm-6 offset-sm-3">
{% if instance.image %}
<img src="{{ instance.image.url }}" class="img-responsive" />
{% endif %}
<h1> {{ title }} <small> {% if instance.draft %} <span style="color:red">{% trans "Draft" %}</span> {% endif %}</small></h1>
{% if instance.user.get_full_name %}
<p> {% trans "Autor:" %} {{ instance.user.get_full_name }}</p>
{% endif %}
{{ instance.location |linebreaks }} <br/>
{{ instance.content |linebreaks }} <br/>
Facebook
Twitter
<a href="https://www.linkedin.com/shareArticle?mini=true&url={{ request.build_absolute_uri }}/&title={{ instance.title }}&source={{ request.build_absolute_uri }}">
Linkedin </a>
Reddit
<a href='https://plus.google.com/share?url={{ request.build_absolute_uri }}'>GooglePlus</a>
</div>
</div>
{% include 'navbar_bottom.html' %}
{% endblock content%}
My views:
from contact.forms import ContactForm
from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from contact.forms import ContactForm
from django.utils.translation import ugettext_lazy as _
import requests
from django.conf import settings
from django.contrib import messages
def index(request):
return render(request, 'home.html')
def board(request):
return render(request, 'board.html')
def persoanefizice(request):
return render(request, 'persoanefizice.html')
def consultanta(request):
return render(request, 'consultanta.html')
def cyberintelligence(request):
return render(request, 'cyberintelligence.html')
#
# def pay(request):
# return render(request, 'pay.html')
def blog(request):
return render(request, 'blog.html')
def contact(request):
if request.method == 'GET':
form = ContactForm()
else:
form = ContactForm(request.POST)
if form.is_valid():
contact_name = form.cleaned_data['numele_dumneavoastra']
contact_phone = form.cleaned_data['numarul_de_telefon']
# contact_period = form.cleaned_data['perioada_cand_va_putem_contacta']
subject = contact_name + " | " + contact_phone
content = form.cleaned_data['mesajul_dumneavoastra']
contact_email = form.cleaned_data['emailul_dumneavoastra']
''' Begin reCAPTCHA validation '''
recaptcha_response = request.POST.get('g-recaptcha-response')
data = {
'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY,
'response': recaptcha_response
}
r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data)
result = r.json()
''' End reCAPTCHA validation '''
if result['success']:
try:
send_mail(subject,content,contact_email, ['greatjobdone770#gmail.com'])
except BadHeaderError:
return HttpResponse('Invalid header found.')
return redirect('success')
else:
form = ContactForm()
return render(request, "contact.html", {'form': form})
def success(request):
return HttpResponse('Succes! Multumim pt mesajul trimis.')