为 Django 中的所有用户创建一个主题 public
Making a topic public to all users in Django
我有一个项目,用户可以在其中输入主题并可以选择将主题设为 public 或私有。我希望所有 public 主题都对所有人可见,而私有主题仅对该主题的所有者可见(项目来自 Python 速成课程练习 20-5)。
当我点击我的项目时我没有收到任何错误,但是当我创建一个新主题和 select "public" 选项时,它仍然没有显示 public 查看。
我研究过类似的问题并遵循了此处的所有建议
How to make a topic public to all users in django? and here 运气不好。
我猜我的查询集没有正确呈现数据?我也阅读了有关查询集的 Django 文档,但我尝试过的任何方法都没有奏效。我真的是编程新手,所以我们将不胜感激。谢谢!
这是我的 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 %}
和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})}
和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 %}
编辑:
在 hasnain095 的帮助下,我已经让项目按预期工作了。这是我更新的 new_topic.html
。我仍然不明白复选框是如何生成的,因为我删除了我认为专门生成它的 html,但由于它仍在工作,我很满意。
{% 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 %}
我认为问题在于您在主题表单中仅指定了“文本”字段:
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
但是在new_topic.html文件中,你只有一个复选框输入,没有地方可以输入文本
<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 %}
您的 "Make post public?" 复选框正在映射到您主题的字段 "text"。
要修复:
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text', 'public']
labels = {'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>
<input class="form-input" type="input" value=True id="text1" />
<label class="form-label" for="text1">
<p>Text<p/>
</label>
</div>
使用联合添加到查询集:
def topics(request):
"""Shows all topics"""
# Gets public topics (renamed to topic_set to not shadow function name)
topic_set = Topic.objects.filter(public=True).order_by('date_added')
# Add private topics, if any. We save some work by not including the public
# topics.
if request.user.is_authenticated:
topic_set = topic_set.union(
Topic.objects.filter(public=False, owner=request.user)
)
context = {'topics': topic_set}
return render(request, 'learning_logs/topics.html', context)
旁注:将索引添加到您筛选的字段:
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, db_index=True)
def __str__(self):
"""Return a string representation of the model"""
return self.text
使用 union 将私有主题附加到 public 主题后,它对我有用,但可能有些不同。罗列如下,希望对你有所帮助:
views.py
def check_topic_owner(topic, request):
if not topic.public:
if topic.owner != request.user:
raise Http404
def topics(request):
#Gets public topics
public_topics = Topic.objects.filter(public=True)
#Gets private topics and append the public topic
if request.user.is_authenticated:
private_topics = Topic.objects.filter(owner=request.user)
topics = public_topics.union(private_topics).order_by('date_added')
else:
topics = public_topics
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
models.py
class Topic(models.Model):
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 self.text
我有一个项目,用户可以在其中输入主题并可以选择将主题设为 public 或私有。我希望所有 public 主题都对所有人可见,而私有主题仅对该主题的所有者可见(项目来自 Python 速成课程练习 20-5)。 当我点击我的项目时我没有收到任何错误,但是当我创建一个新主题和 select "public" 选项时,它仍然没有显示 public 查看。
我研究过类似的问题并遵循了此处的所有建议
How to make a topic public to all users in django? and here
我猜我的查询集没有正确呈现数据?我也阅读了有关查询集的 Django 文档,但我尝试过的任何方法都没有奏效。我真的是编程新手,所以我们将不胜感激。谢谢!
这是我的 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 %}
和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})}
和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 %}
编辑:
在 hasnain095 的帮助下,我已经让项目按预期工作了。这是我更新的 new_topic.html
。我仍然不明白复选框是如何生成的,因为我删除了我认为专门生成它的 html,但由于它仍在工作,我很满意。
{% 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 %}
我认为问题在于您在主题表单中仅指定了“文本”字段:
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
但是在new_topic.html文件中,你只有一个复选框输入,没有地方可以输入文本
<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 %}
您的 "Make post public?" 复选框正在映射到您主题的字段 "text"。
要修复:
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text', 'public']
labels = {'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>
<input class="form-input" type="input" value=True id="text1" />
<label class="form-label" for="text1">
<p>Text<p/>
</label>
</div>
使用联合添加到查询集:
def topics(request):
"""Shows all topics"""
# Gets public topics (renamed to topic_set to not shadow function name)
topic_set = Topic.objects.filter(public=True).order_by('date_added')
# Add private topics, if any. We save some work by not including the public
# topics.
if request.user.is_authenticated:
topic_set = topic_set.union(
Topic.objects.filter(public=False, owner=request.user)
)
context = {'topics': topic_set}
return render(request, 'learning_logs/topics.html', context)
旁注:将索引添加到您筛选的字段:
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, db_index=True)
def __str__(self):
"""Return a string representation of the model"""
return self.text
使用 union 将私有主题附加到 public 主题后,它对我有用,但可能有些不同。罗列如下,希望对你有所帮助: views.py
def check_topic_owner(topic, request):
if not topic.public:
if topic.owner != request.user:
raise Http404
def topics(request):
#Gets public topics
public_topics = Topic.objects.filter(public=True)
#Gets private topics and append the public topic
if request.user.is_authenticated:
private_topics = Topic.objects.filter(owner=request.user)
topics = public_topics.union(private_topics).order_by('date_added')
else:
topics = public_topics
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
models.py
class Topic(models.Model):
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 self.text