Displaying comments for questions only when they exist - python

I need to display messages on a Django template. Each message can have 0 to many comments. I need to display the comments for each message. However, if a message has no comments, then it is 'None' and I can't iterate over it. The problem is occurring in Django templates.
#models.py
class User(models.Model):
firstName = models.CharField(max_length = 255)
lastName = models.CharField(max_length = 255)
email = models.CharField(max_length = 255)
birthDate = models.DateField()
password = models.CharField(max_length = 255)
createdAt = models.DateTimeField(auto_now_add = True)
updatedAt = models.DateTimeField(auto_now = True)
objects = UserManager()
class Message(models.Model):
content = models.TextField()
user = models.ForeignKey(User, related_name = "messages")
createdAt = models.DateTimeField(auto_now_add = True)
updatedAt = models.DateTimeField(auto_now = True)
objects = UserManager()
class Comment(models.Model):
content = models.TextField()
message = models.ForeignKey(Message, related_name = "comments", default = [])
createdAt = models.DateTimeField(auto_now_add = True)
updatedAt = models.DateTimeField(auto_now = True)
objects = UserManager()
#views.py
#Main wall page
#Renders wall.html
def wall(request):
wallDict = {
"message" : Message.objects.all()
}
return render(request, "loginRegApp/wall.html", wallDict)
#wall.html
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
</head>
<body>
<div class="container">
Log out
<form action="message/create" method="post">
{% csrf_token %}
<h4>Post a message</h4>
<textarea name="message"></textarea>
<input type="submit" value="Post a message">
</form>
{% for message in messages %}
<div>
<h6>{{message.user.firstName}} {{message.user.lastName}} - {{message.createdAt}}</h6>
<p>{{message.content}}</p>
{% if message.comments %}
{% for comment in message.comments %}
<h6>Comment: {{message.user.firstName}} {{message.user.lastName}} - {{comment.createdAt}}</h6>
<p>{{comment.content</p>
{% endfor %}
{% endif %}
<form action="comment/{{message.id}}/create" method="post">
{% csrf_token %}
<textarea name="comment"></textarea>
<input type="submit" value="Post a comment">
</form>
</div>
{% endfor %}
</div>
</body>
</html>
I am trying to get all comments to display, whether 0 or 100.

You should use .all in your template to have access to the QuerySet that contains the comments. There is no need to use {% if ... %} and {% endif %}:
{% for comment in message.comments.all %}
<h6>Comment: {{message.user.firstName}} {{message.user.lastName}} - {{comment.createdAt}}</h6>
<p>{{comment.content</p>
{% endfor %}
In your view, you might want to use .prefetch_related(..) [Django-doc] here to avoid making an extra query per message to fetch the related comments, like:
def wall(request):
wallDict = {
'message' : Message.objects.prefetch_related(
'comments', 'comments__user'
).all()
}
return render(request, 'loginRegApp/wall.html', wallDict)

Related

Check if logged in user is the author of a post | Django | If-else doesn't work

I want to check if the logged in user is the author of a post in my Forum. I have written some code to figure that out:
<div class="right-section-posts">
user: {{ user }} <!--Output: Admin-->
author: {{ post.author }} <!--Output: Admin-->
{% if user == post.author %}
<form action="DELETE">
{% csrf_token %}
<button type="submit" class="delete-btn" name="post-id" value="{{ post.id }}">Delete</button>
</form>
<button class="edit-btn">Edit</button>
{% endif %}
</div>
They both output the same but the statement returns false! Why?
Models.py
class Post(models.Model):
vote_count = models.IntegerField(default=0)
id = models.BigAutoField(primary_key=True)
created_at = models.DateField(default=date.today)
title = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
tags = models.CharField(max_length=200)
author = models.CharField(max_length=100, default="none")
def __str__(self):
return str(self.id) + ' ' + self.title
I tried different ways to get the Current user and the author. Doesn't work to.
(I think you might say that I should use ForeignKey instead of ´CharField´, when using that I get this Error:
ERROR: Column forum_app_post.author_id does not exist.
LINE 1: ...app_post". "description", "forum_app_post". "tags", "forum_app...
^
HINT: Perhaps the intention was to refer to the "forum_app_post.author" column.
)
The author field cannot be a CharField because it represents the user. You need to set author field as foreignkey.
You need to update your model like this:
from django.contrib.auth.models import User
class Post(models.Model):
vote_count = models.IntegerField(default=0)
id = models.BigAutoField(primary_key=True)
created_at = models.DateField(default=date.today)
title = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
tags = models.CharField(max_length=200)
author = models.ForeignKey(User,on_delete= models.CASCADE, verbose_name='Post Author')
def __str__(self):
return str(self.id) + ' ' + self.title
If you want to check the logged in user from all the registered posts, you should get all the posts first.
def get_all_posts(request):
posts = Post.objects.filter.all()
context = {
"posts" : posts,
}
return render(request,"my_page.html",context)
Then in the html page :
<div class="right-section-posts">
{% if posts %}
{% for post in posts %}
{% if request.user == post.author %}
<!--do what you want here-->
{% else %}
{% endif %}
{% endfor %}
{% else %}
<div class="alert alert-info">You have no registered post yet!</div>
<!-- /.container-fluid -->
</div>
{% endif %}
</div>
I also recommend using django-taggit for tags.

Customize form field according to other field

Please give me advice for my following question. I have added corresponding script at the bottom of this sentence. Thank you in advance!!!
What I want to do: Customize form field according to the target field specified in the database as shown in following image.
Current situation
All the radio buttons in Ecms table are listed in one column
html file
{% extends "base.html" %}
(% load widget_tweaks %}
{% block content %}
<form method="post" enctype="multipart/form-data">
<h4 style="margin-top: 0">Project Upload</h4>
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{hidden}}
{% endfor %}
{% for field in form.visible_fields %}
<div class="form-group">
<label for="{{field.id_for_label}}">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
<button type="submit">Upload</button>
</form>
{% endblock %}
Model.py(parent)
class html(models.Model):
project = models.CharField(max_length=50, blank=True)
version = models.IntegerField(default=0)
ecms=models.ManyToManyField(ecm, blank=True)
diff = models.TextField(blank=True)
PROGRAM_CHOICES = (
('Office', 'General office'),
('Residential', 'Residential'),
('Retail', 'Retail'),
('Restaurant', 'Restaurant'),
('Grocery', 'Grocery store'),
('Medilcal', 'Medilcal office'),
('Research', 'R&D or laboratory'),
('Hotel', 'Hotel'),
('Daycare', 'Daycare'),
('K-12', 'Educational,K-12'),
('Postsecondary', 'Educational,postsecondary'),
('Airport', 'Airport'),
('DataCenter','Data Center'),
('DistributionCenter','Distribution center,warehouse')
)
program = models.CharField(max_length=20, choices=PROGRAM_CHOICES, default='Retail')
LOCATION_CHOICES = (
('Beijing', 'Beijing'),
('China', 'China'),
('Hong Kong', 'Hong Kong'),
('Japan', 'Japan'),
('Shanghai', 'Shanghai'),
('Shenzhen', 'Shenzhen'),
('Taiwan', 'Taiwan'),
('USA', 'United States')
)
location = models.CharField(max_length=15, choices=LOCATION_CHOICES, default="Hong Kong")
CERTIFICATE_CHOICES = (
('LEED_v3', 'LEED_v3'),
('LEED_v4', 'LEED_v4'),
('BEAM+', 'BEAM+'),
('WELL', 'WELL'),
('No certificate','No certificate')
)
certificate = models.CharField(max_length=20, choices=CERTIFICATE_CHOICES, default='BEAM+')
user = models.CharField(max_length=20, default='test')
html = models.FileField(upload_to=dir_path)
uploaded_at = models.DateTimeField(auto_now_add=True)
Model.py
class ecm(models.Model):
name = models.CharField(max_length=50, blank=True)
TARGET_CHOICES = (
('Heating', 'Heating'),
('Cooling', 'Cooling'),
('Fan', 'Fan'),
('Lighting', 'Lighting'),
('Equipment', 'Equipment'),
('Renewable','Renewable Energy'),
('Hot Water','Hot Water System'),
('Others', 'Others'),
)
target=models.CharField(max_length=20, choices=TARGET_CHOICES, default='Others')
description = models.TextField(blank=True)
link=models.URLField(blank=True)
def __str__(self):
return self.name
views.py
def model_form_upload(request):
if request.method == 'POST':
if form.is_valid():
newhtml = form.save()
newhtml.save()
else:
form = DocumentForm()
return render(request, 'model_form_upload.html', {'form': form})
You should render your fields manually, not iterate over them. I suggest wrapping each of the columns you want into a div and setting width to the resulting divs.

ModelChoiceField django

I have created a Django form to get the data from user and search that given data in database models.
But i am not able to use the dropdown functionality correctly. I have used ModelChoiceField but I am getting it empty.
I have three fields(forms.py) which i am searching in the database.
models.py
class Release(models.Model):
number = models.CharField(max_length=50,unique=True)
notes = models.CharField(max_length=50)
changes = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.number)
class Metamodule(models.Model):
name = models.CharField(max_length=50,unique=True)
version = models.IntegerField(default=0)
release = models.ForeignKey(Release,related_name="num")
createdate = models.DateField(auto_now=True, null=True)
createdby = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.name)
class Module(models.Model):
name = models.CharField(max_length=50,unique=True)
version = models.IntegerField(default=0)
metamodule = models.ForeignKey(Metamodule,related_name="metaname")
createdate = models.DateField(auto_now=True, null=True)
changes = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.name)
forms.py
class ModuleForm(forms.Form):
release_num = forms.ModelChoiceField(queryset=Release.objects.all().values('number'),empty_label='Pick a Release')
metamodule_name = forms.CharField(max_length=50)
module_name = forms.CharField(max_length=50)
views.py
from django.shortcuts import render
from search.forms import ModuleForm
from django.http import HttpResponse
from search.models import Module,Metamodule,Release
def searchview(request):
if request.method == 'GET':
form = ModuleForm(request.GET)
if form.is_valid():
release_num = form.cleaned_data['release_num']
metamodule_name = form.cleaned_data['metamodule_name']
module_name = form.cleaned_data['module_name']
results = Module.objects.filter(metamodule__release__number=release_num).filter(metamodule__name=metamodule_name).filter(name=module_name)
return render(request,'search/search_result.html',{'form': form, 'results': results})
else:
form = ModuleForm()
return render(request, 'search/search_form.html',{'form': form})
search_form.html
<html>
<head>
<title>Search</title>
</head>
<body>
{% if error %}
<p style="color: red;">Please submit a search term.</p>
{% endif %}
<form action="/search/" method="get">
<select name="release_num">
{% for release_num in release_num %}
<option value="{{ release_num.number }}">{{ release_num.number }}</option>
{% endfor %}
</select>
<p><label for="metamodule_name">Metamodule:</label>
<input type="text" name="metamodule_name">
<p><label for="module_name">Module:</label>
<input type="text" name="module_name">
<input type="submit" value="Search">
</form>
</body>
</html>
try in the search_form.html:
<form action="/search/" method="get">
{{ form.release_num }}
{{ form.metamodule_name }}
{{ form.module_name }}

Form posting Django

I can't get my django app to post to the db. I'm trying to pass my foreign key so I can post it correctly.
Sorry if it's something basic I'm missing I'm just starting. I think it never gets to form = ResultForm(request.POST). And just gives me the form = ResultForm.
Here is my code:
Model:
class Result(models.Model):
category = models.ForeignKey(Category)
category_result = models.CharField(max_length=200)
rating = models.DecimalField('', '', 8, 3)
votes = models.IntegerField(default=0)
created_by = models.IntegerField(default=0, null=True, blank=True)
created_on = models.DateTimeField('created on')
def __unicode__(self):
return self.category_result
Form:
class ResultForm(forms.ModelForm):
category_result = forms.CharField(max_length=200,help_text="Your best line")
rating = forms.DecimalField(widget=forms.HiddenInput(), initial=0)
votes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
created_by = forms.IntegerField(widget=forms.HiddenInput(), initial=1)
category = forms.IntegerField(widget=forms.HiddenInput())
class Meta:
model = Result
fields = ('category_result', 'rating', 'votes')
view:
def help_out(request, category_id):
if request.method == 'POST':
form = ResultForm(request.POST)
if form.is_valid():
form.save(commit=False)
form.category = category_id
form.save()
return index(request)
else:
print form.errors
else:
form = ResultForm
context = {'form': form, 'category_id': category_id}
return render(request,'pocketwingman/help_out.html', context)
template:
<!DOCTYPE html>
<html>
<head>
<title>Pocketwingman</title>
</head>
<body>
<h1>Add a Result</h1>
<form id="result_form" method="post" action="/pocketwingman/help_out/{{category_id}}/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text}}
{{ field }}
{% endfor %}
<input type="submit" name="submit" value="Create Line" />
</form>
</body>
</html>
url config:
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^(?P<category_id>\d+)/$', views.help_me, name='help_me'),
url(r'^help_out/(?P<category_id>\d+)/$', views.help_out, name='help_out'),
)
You should initiate your form if it's not a POST:
else:
form = ResultForm()
append () to form class.

Most effective way to create Attending Event option button [Django/Python]?

Trying to implement an "Attending" button. It's simple (or so I thought). A user with a profile clicks "Attending", and a checkmark appears. Can't quite get this to work on the Django/Python side of things. ie: Put that user who clicked 'Attending' into the attendee(list) within the Event.
Template:
{% if is_attending %}
<button class="btn" disabled="disabled">
<i class="icon-ok-sign"></i> Attending
</button>
{% else %}
<form class="left" method="POST" action="/profile/event/{{ event.id }}/">
{% csrf_token %}
<input type="hidden" name="profile_id" value="user" />
<button class="btn">
Attending
</button>
</form>
{% endif %}
Models:
class Event(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
owner = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=200)
location = models.CharField(max_length=200)
start_date = models.DateTimeField(auto_now=False, auto_now_add=False)
end_date = models.DateTimeField(auto_now=False, auto_now_add=False)
about = models.TextField(null=True, blank=True)
attendees = models.ManyToManyField(Profile, null=True, blank=True)
View:
#login_required
def attending_event(request, event_id):
event = get_object_or_404(Event, id=event_id)
if request.method == 'POST':
try:
id = request.POST.get('profile_id')
attendee = Profile.objects.get(id=id)
relationship = Event.objects.create(attendees__user=attendee)
is_attending = True
except:
pass
return HttpResponseRedirect('/profile/event/' + event_id + '/')
else:
if not Event.objects.filter(attendees__user=request.user).exists():
is_attending = False
data = {
'is_attending': is_attending
}
return render_to_response('profiles/event.html', data, context_instance=RequestContext(request))
Maybe there's something I'm missing and can't see what it is I'm doing wrong. But if anyone could offer some insight/advice about how to go about completing this; I'd really appreciate it.
Just giving you hint, change it according to your needs
Template:
{% if is_attending %}
<button class="btn"> # this code will executes when is_attending is True
<i class="icon-ok-sign"></i> Attending
</button>
{% else %}
<form class="left" method="POST" action="/profile/event/{{ event.id }}/"> # Always user reverse urls instead of Hard coded
{% csrf_token %}
<input type="hidden" name="profile_id" value="{{profile.id}}" />
<button class="btn">
Attending
</button>
</form>
{% endif %}
View:
#login_required
def event_profile(request, event_id)
event = get_object_or_404(Event, id=event_id)
if request.method == 'POST':
try:
id = request.POST.get('profile_id')
attendee = Profile.objects.get(id=id)
relationship = Event.objects.create(attendees__user=attendee, .... ) # set other variable you want
is_attending = True
else:
# check in your event either your profile user is already attending or not? and set is_attending variable according to it
data = {
'is_attending': is_attending,
....
}
return render_to_response('my_template.html',
data,
context_instance=RequestContext(request))

Categories