Pointing Django comments to specific objects - python

I am having trouble with pointing specific comments to specific objects in my Django website. On the HTML page below, 5 posts along with their respective attributes are displayed. Each post has it's own comment_form where users can leave comments. Yet, when a comment is left, ALL of the posts share the same comments, instead of their own unique set of comments. Does any one have a recommended way for me to give each post their own distinct set of comments so that they all aren't sharing the same ones?
Here is my current HTML:
<div class="mainContent">
<div class="content">
{% for post in posts %}
<article class="topContent">
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.body }}</p>
<h6><i>published {{ post.pub_date }}</i></h6>
<div class="commentForm">
{% for comment in comments %}
<p id="commentP">{{ comment.comment }} - {{ comment.name }}</p>
{% endfor %}
</div>
<form method="POST" action="">
{% csrf_token %}
<div id='comment_form'>
<div id="namePrompt">
<p> Name:</p>
</div>
<div id="formName">
{{form.name}}
</div>
<div id="commentPrompt">
<p> Comment: </p>
<div id="formComment">
{{form.comment}}
</div>
<div id="submitBtn">
<input type='submit' name='submit' value='Add Comment'>
</div>
</div>
</form>
</div>
</article>
{% endfor %}
</div>
</div>
here is the view:
def projects(request):
print request
posts = ProjectsPost.objects.all()
comment_from_db = ProjectComment.objects.all()
form = ProjectCommentForm(request.POST or None)
if form.is_valid():
new_form = form.save(commit=False)
name = form.cleaned_data['name']
comment = form.cleaned_data['comment']
context_comment = ProjectComment.objects.get_or_create(name=name, comment=comment)
print context_comment
template = "blog/projects.html"
context = {"form":form}
project_posts = {'posts':posts}
return render(request, template, {'form':form, 'posts':posts, 'comments':comment_from_db})`

I'm assuming that your models look like these:
class ProjectPosts(models.Model):
....
class ProjectComments(models.Model):
....
post = models.ForeignKey(ProjectPosts)
Then in your template, you need to do this:
<div class="commentForm">
{% for comment in post.projectcomments_set.all %}
<p id="commentP">{{ comment.comment }} - {{ comment.name }}</p>
{% endfor %}
</div>
Yeah. You can iterate over your reverse FK relations like that in templates.
EDIT: I'm seeing now that you're taking all the comments in your view, which is not for a specific post too. You don't need to do that. Whenever you need to show comments for a specific post, do in your template what I showed above.

If there isn't an association between a post and it's related comment then each time you query the db you are getting all the comments and passing it on to the template.
As you mentioned in your own comment, adding a foreignkey on the Comment model should work. So when you query the comments for a particular article then you should be able to query only the comments related to that article.
So in essence something like this:
class ProjectPosts(models.Model):
....
class ProjectComments(models.Model):
....
post = models.ForeignKey(ProjectPosts)
And when retrieving all the comments related to a post you can do something like this:
post_comment = PorjectPosts.projectcomments_set.filter(id=foo)
You can read up more on realationships in the Django ORM here.

Related

Is there a way to dynamically populate a value field in Flask-WTF form?

I have a create and an update
notes views.
Each view has the same form to create/update a note.
I was wondering on a good way to render the value of my content only in the update view but not in the create view.
Here what I have today :
<div class="field">
{{ form.title.label }}
{% if request.endpoint == 'notes.update' %}
<div class="control">
{{ form.title(class="input", value=note.title) }}
</div>
{% else %}
<div class="control">
{{ form.title(class="input"}}
</div>
{% endif %}
</div>
I use a condition on the endpoint to do what I want but I don't think it's a good way to do this.
Thank you for help 🙏
Populate the form in your endpoint.
form = NotesForm(request.form)
form.populate_obj(note)
There is a solution for dictionaries, too.
form = NotesForm(request.form, data={'title':'Untitled Note'})

How set records priority in order to display HTML?

I am setting up a website in flask, and I want to set a post order from newest to oldest blog post. Posts are inside the database, where I created an id, where the oldest post has id = 0 and the newest post = 1, and so on. It turns out that in jinja html, the post starts from 0 to 1, and want the opposite.
I was searching just to set an ID for each line, but I need help in establishing this order, thank you for your attention.
this is the code of my html page with jinja
{% extends "layout.html" %}
{% block content %}
{% for post in posts %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="/{{post.url}}">{{ post.title }} {{post.id}}</a>
<small class="text-muted">{{ post.author }}</small>
</div>
<div id="description_2" class="article-content"><a>{{ post.short_description }}</a></div>
</div>
{%endif%}
</article>
{% endfor %}
{% endblock content %}
In order to display posts sorted by id in descending order you need to order the query before passing it to the context.
posts = Post.query.order_by(Post.id.desc()).all()

How to use Django Haystack whoosh search field in multiple application templates

I have implemented a working Django 1.6 haystack/whoosh search field following Mike Hibbert's tutorial:https://www.youtube.com/watch?v=B-n6_m66TmA. The implementation works in a twitter bootstrap search field in the navbar in the url 'search'. I'd like to use the implementation in several pages in my application but it doesn't work.
I've tried with implementing the search.html code in other pages with search bars but it changes the search url prefix from 'search/...' to the page url, e.g. to 'front/...' on the frontpage. I've also tried to include the search.html in other pages, both as the block content and with an include tag in the template but it hasn't worked.
# in app/templates/search/indexes/search.html
{% extends 'base_searches.html' %}
{% block content %}
<form method="get" action=".">
<table>
<tr><th><label for="id_q"></label></th><td><input type="text" id="id_q"
name="q" placeholder="Search..." class="form-control" /><button
class="btn btn-success" type="submit" value="Search"><spaclass="glyphicon
glyphicon-search"></span></button></td></tr>
<tr>
<td> </td>
{% if query %}
{% for result in page.object_list %}
<div class="alert alert-success" role="alert">
Hi, {{ user }}, here's the found database match for your search
<a href="{{ result.object.get_absolute_url }}">
{{result.object.title }}.</a></div>
{% empty %}
<div class="alert alert-info" role="alert">
<strong>Hi {{ user }}, there's no match found in the
database for your search !.</strong>
</div>
{% endfor %}
{% endif %}
<div class="col-xs-6 col-sm-3 sidebar-offcanvas" id="sidebar">
<!--/.sidebar-offcanvas-->
<!--/row-->
<hr>
<td>
</td>
</tr>
</table>
</form>
</body>
</html>
{% endblock %}
# in models.py for each indexed model field
def get_absolute_url(self):
return '%s' % self.id
# in app/templates/base_searches.html
<form class="navbar-form navbar-right" id="search">{% csrf_token %}
<center><h> <td colspan="1" id="content">{% block content %}}
{% endblock %} </center></td></h>
<ul id="search-results">
</ul>
</form>
in urls.py
from haystack.query import SearchQuerySet
url(r'^search/',include('haystack.urls'),name='haystack_search'),
# in search_indexes.py
from haystack import indexes
from app.models import Article
class ArticleIndex(indexes.SearchIndex, indexes.Indexable):
text= indexes.CharField(document=True,use_template=True)
content = indexes.CharField(model_attr='description')
content_auto = indexes.EdgeNgramField(model_attr='title')
def get_model(self):
return Article
def index_queryset(self, using=None):
"""used when the entire index for model is updated """
return self.get_model().objects.all()
# in app/templates/search/indexes/appname/article_text.txt
{{ object.title }}
{{ object.content}}
How do I include the search.html in other pages, as I've included it in the navbar in base_searches.html, and maintain the prefix search/..searchresult for the get_absolut_url function for the search result object and not the url prefix for other pages that I'm trying to include it in, e.g. front/..searchresult ? when trying to implement it in the frontpage with url front/, or are there better ways to use the haystack whoosh search in search fields in multiple application pages ?
I have solved this problem by adding http://{{ request.get_host }}/search" to the search form action.
`<form method="get" action="http://{{ request.get_host }}/search"`
The action="." will reference to your current page and the request will be redirected to your current view. With adding the host URL to your action it will redirect your query to the search view no matter on which page you are.

Inserting ListView Template in a section of the Homepage using Django 1.11

I have a ListView Template in Django 1.11 that renders to group_list.html. However I want the same view to show in a column in the home page
I also have screenshots below if that helps understanding what I am trying to achieve
I have tried different ways to use {% include 'some.html' %}
1) I tried to make a html page and include it in homepage. but it keeps giving errors
2) I tried to change the group_list.html page into a (insert template) that and tried to insert that, in both the index page and created another template view for groups. but that is giving errors too
Below are my views and templates
Views.py
class GroupCreate(LoginRequiredMixin, CreateView):
model = Group
fields = ('name', 'description')
class GroupList(ListView):
model = Group
class GroupDetail(DetailView):
model = Group
Below is my Index.html and group_list.html
INDEX.HTML
{% extends 'base.html' %}
{% block body %}
<div class="col-md-8" style="background-color:white; border-right:1px solid grey;">
<h4>Groups</h4>
<p>Join a group or make a new Group.</p>
<a style="float:left" class="btn btn-success" href="{% url 'groups:new' %}">Start a Group</a>
<div class="content">
<!--{ % include 'groups/some.html' % } I am trying to insert my -->
</div>
</div>
<div class="col-md-4" style=background-color:white">
<h4>Second Coloumn</h4>
</div>
{% endblock %}
Below is my group_list.html
{% extends 'groups/group_base.html' %}
{% block pre_group %}
<div class="col-md-4">
<div>
<h2>Welcome Back
{{group.user.username}}
</h2>
<h3>Groups</h3>
<p>Welcome to the groups page! Select the Group with the shared interest</p>
</div>
<div>
{% if user.is_authenticated %}
<a class="btn btn-warning" href="{% url 'groups:new' %}"><span class="glyphicon glyphicon-plus-sign"></span> Create a New Group</a>
{% endif %}
</div>
</div>
{% endblock %}
{% block content %}
<div class="col-md-8">
<div class="list-group">
{% for group in object_list %}
<a class="list-group-item" href="{% url 'groups:single' slug=group.slug %}">
<h3 class="list-group-item-heading">{{group.name}}</h3>
<div class="list-group-item-text container-fluid">
{{group.description_html|safe}}
<div class="row">
<div class="col-md-4">
<span class="badge">{{group.members.count}}</span> member{{group.members.count|pluralize}}
</div>
<div class="col-md-4">
<span class="badge">{{group.posts.count}}</span> post{{group.posts.count|pluralize}}
</div>
</div>
</div>
</a>
{% endfor %}
</div>
</div>
{% endblock %}
The HomePage View comes from the root Views they are below
View.py(root directory)
from django.views.generic import TemplateView
class Homepage(TemplateView):
template_name = 'index.html'
class LoggedIn(TemplateView):
template_name = 'test.html'
class LoggedOut(TemplateView):
template_name = 'thanks.html'
I am still learning Django while working on my 1st independent project. I did a some research but could not solve this
I want a list view like this to show on a section of the HomePage
Currently the view works perfectly well on the groups page
In your homepage view you can override get_context_data and add the groups to the context.
class Homepage(TemplateView):
template_name = 'index.html'
def get_context_data(self, **kwargs):
context = super(Homepage, self).get_context_data(**kwargs)
context['object_list'] = Group.objects.all()
return context
In the index.html, you'll have to copy the code from your group_list.html template. To prevent duplication, you could move the code from the content block into a include_groups.html template, then use {% include 'include_groups.html' %} in yourindex.htmlandgroup_list.html` templates.
In this case, since your Homepage view is just a template view, you could use a ListView instead.
class Homepage(ListView):
model = Group
template = 'index.html'
Whichever option you go for, it's useful to understand how to override get_context_data in class based views.

Django - ManagementForm data is missing or has been tampered with

I've been racking my brain over this problem for the past few days and I've read numerous other questions regarding the same error but they all seem to be different cases (not including management form, forgetting to update TOTAL_FORMS, etc etc) and do not resolve my problem. I have a page which could contain multiple formsets in a single HTML form. When I am posting the data back to the server, it fails on the is_valid() check for the formsets with the error in the title. I am new to web development and Django so please forgive me if I made a silly mistake or am taking an approach that will not work.
def purchase(request):
return generic_form_view(request, "inventory_tracking/add_purchases.html",
"Successfully added purchases for %s.",
PurchaseForm,
[formset_factory(PurchaseForm.LiquorForm),
formset_factory(PurchaseForm.NonLiquorForm)])
def generic_form_view(request, template, success_message, ParentForm, FormSets):
if request.method == 'POST':
request_params = copy(request.POST)
parent_form = ParentForm(request_params)
formsets = list(map(lambda form_set: form_set(request_params), FormSets))
if parent_form.is_valid(): # This works.
for formset in formsets:
if formset.is_valid(): # Fails here.
Here is a snippet from my template:
<form action="{% block form_action %}{% endblock %}" method="post">
{% csrf_token %}
<div class="row">
<div class="row">
<div class=" well well-lg">
<div class="row">
{{ parent_form.management_form }}
{% for field in parent_form %}
<div class="col-lg-6">
<div class="form-group">
<label class="control-label">{{ field.label }}</label>
{{ field }}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
<div class="row">
{% for formset in formsets %}
{{ formset.management_form }}
<div class="row">
<div class="well well-lg">
{% for form in formset %}
<div id="{{ form.prefix }}" class="row">
...
I've been trying to debug this and I noticed something a little interesting but since I am not too familiar with Django it could be a red herring. In the POST, I see the management_form data for the formsets I am creating but I do not see the management_form data for the parent formset (in this case PurchaseForm). However the parent_form is passing validation and the other formsets are not.
I expected this to be a silly problem and I turned about to be right! When my generic_form_view method creates the formsets on the GET request I was adding a prefix like the documentation mentioned but I was not adding a prefix when creating the formsets on the POST.

Categories

Resources