Issue
I've got a project where users can enter topics and have the option to make the topic public or private. I want all public topics to be visible to everyone, and private topics to only be visible by the owner of that topic (Project is from Python Crash Course exercise 20-5). I'm not getting any errors when I click through my project, but when I create a new topic and select the "public" option, it is still not showing up for public viewing.
I've researched similar problems and followed all the suggestions here How to make a topic public to all users in django? and here Django - How to make the topics, that you create public? Learning Log Project with no luck.
I'm guessing my queryset is not rendering data correctly? I've read the Django documentation on querysets as well, but nothing I've tried has worked. I'm really new to programming so any help would be appreciated. Thank you!
Here's my models.py
:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Topic(models.Model):
"""A topic the user is learning about"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
public = models.BooleanField(default=False)
def __str__(self):
"""Return a string representation of the model"""
return self.text
class Entry(models.Model):
"""Something specific learned about a topic"""
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entries'
def __str__(self):
"""Retrun a string representation of the model"""
if len(self.text) < 50:
return f"{self.text}"
else:
return f"{self.text[:50]}..."
views.py
:
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.http import Http404
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
# Create your views here.
def index(request):
"""The home page for Learning Log"""
return render(request, 'learning_logs/index.html')
#Checks whether logged in user has access to topic
def check_topic_owner(request, topic):
if topic.owner != request.user:
raise Http404
def topics(request):
"""Shows all topics"""
#Gets public topics
public_topics = Topic.objects.filter(public=True).order_by('date_added')
#Gets private topics
if request.user.is_authenticated:
private_topics = Topic.objects.filter(owner=request.user).order_by('date_added')
topics = public_topics | private_topics
else:
topics = public_topics
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
def topic(request, topic_id):
"""Show a single topic and all its entries"""
topic = get_object_or_404(Topic, id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)
@login_required
def new_topic(request):
"""Add a new topic"""
if request.method != 'POST':
#No data submitted; create a blank form.
form = TopicForm()
else:
#POST data submitted; process data
form = TopicForm(data=request.POST)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user
new_topic.save()
return redirect('learning_logs:topics')
#Display a blank or invalid form
context = {'form': form}
return render(request, 'learning_logs/new_topic.html', context)
@login_required
def new_entry(request, topic_id):
"""Add a new entry for a particular topic"""
topic = get_object_or_404(Topic, id=topic_id)
check_topic_owner(request, topic)
if request.method != 'POST':
#No data submitted, create a blank form
form = EntryForm()
else:
#POST data submitted; process data
form = EntryForm(data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.topic = topic
if new_entry.topic.owner == request.user:
new_entry.save()
else:
return Http404
return redirect('learning_logs:topic', topic_id=topic_id)
#Display a blank or invalid form
context = {'topic': topic, 'form': form}
return render(request, 'learning_logs/new_entry.html', context)
@login_required
def edit_entry(request, entry_id):
"""Edit an existing entry"""
entry = get_object_or_404(Entry, id=entry_id)
topic = entry.topic
check_topic_owner(request, topic)
if request.method != 'POST':
#Initial request; prefill with the current entry
form = EntryForm(instance=entry)
else:
#POST data submitted; process data
form = EntryForm(instance=entry, data=request.POST)
if form.is_valid():
form.save()
return redirect('learning_logs:topic', topic_id=topic.id)
context = {'entry': entry, 'topic': topic, 'form': form}
return render(request, 'learning_logs/edit_entry.html', context)
new_topic.html
:
{% load bootstrap4 %}
{% block page_header %}
<h3>Add a new topic:</h3>
{% endblock page_header %}
{% block content %}
<form method="post" action="{% url 'learning_logs:new_topic' %}" class="form">
{% csrf_token %}
{% bootstrap_form form %}
<div class="form-check">
<input class="form-check-input" type="checkbox" value=True id="public" />
<label class="form-check-label" for="public">
<p>Make post public?<p/>
</label>
</div>
{% buttons %}
<button name="submit" class="btn btn-primary">Add topic</button>
{% endbuttons %}
</form>
{% endblock content %}
And forms.py
:
from .models import Topic, Entry
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols': 80})}
And topics.html
:
{% block page_header %}
<h1>Topics</h1>
{% endblock page_header %}
{% block content %}
<ul>
{% for topic in topics %}
<li><h4>
<a href="{%url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</h4></li>
{% empty %}
<li><h4>No topics have been added yet.</h4></li>
{% endfor %}
</ul>
<h4><a href="{% url 'learning_logs:new_topic' %}">Add a new topic</a></h4>
{% endblock content %}
Edit:
I've gotten the project to work as expected now with the help from hasnain095. Here is my updated new_topic.html
. I still don't understand how the checkbox is being generated since I've deleted the html which I thought was specifically generating it, but since it's still working, I'm content.
{% extends "learning_logs/base.html" %}
{% load bootstrap4 %}
{% block page_header %}
<h3>Add a new topic:</h3>
{% endblock page_header %}
{% block content %}
<form method="post" action="{% url 'learning_logs:new_topic' %}" class="form">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary">Add topic</button>
{% endbuttons %}
</form>
{% endblock content %}
Solution
I think the issue is that you've only specified the field 'text in your Topic Form:
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
but in new_topic.html file, you have only one checkbox input, no place to enter the text
<div class="form-check">
<input class="form-check-input" type="checkbox" value=True id="public" />
<label class="form-check-label" for="public">
<p>Make post public?<p/>
</label>
</div>
{% buttons %}
<button name="submit" class="btn btn-primary">Add topic</button>
{% endbuttons %}
Your checkbox for "Make post public?" is getting mapped to the field "text" of your Topic.
To fix do:
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text', 'public']
labels = {'text': ''}
and
<div class="form-check">
<input class="form-check-input" type="checkbox" value=True id="public" />
<label class="form-check-label" for="public">
<p>Make post public?<p/>
</label>
<input class="form-input" type="input" value=True id="text1" />
<label class="form-label" for="text1">
<p>Text<p/>
</label>
</div>
Answered By - hasnain095
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.