如何在django中向所有用户公开主题?
有问题
我正在创建一个项目,您可以在其中创建主题,对于未经身份验证的用户,主题可以是私有的或公开的.然后,您可以在每个主题中输入多个条目,以应用于该主题.现在,我尝试在new_topic.html中创建一个复选框,如果您选中该复选框,它的计算结果为True,否则为False但是如果不登录我就看不到这个话题
I am creating a project, where you can make topics, that can be private or public to unauthenticated users. In every topic, you can then make several entries, applying to that topic. Now I'm trying to make a checkbox in my new_topic.html, where if you check it, it evaluates to True, if not, to False But I can't see the topic without logging in
我想要的
我想通过将视图中的public属性更改为True来向尚未登录的用户显示公共主题,但是我不知道如何实现它们
I would like to show public subjects to users who have not logged in by changing the public property to True in the view, but I do not know how to implement them
我尝试过的事情
我玩过查询集topic.public == True但我不知道该怎么用
I played with the query set topic.public == True but I don't know how to use that
代码
我的/learning_logs/modles.py看起来像这样:
My /learning_logs/modles.py looks like this:
from django.db import models
from django.contrib.auth.models import User
class Topic(models.Model):
"""topic은 사용자가 공부하고 있는 주제이다."""
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
class Entry(models.Model):
"""주제에 관해 공부한 내용"""
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):
"""모델에 관한 정보를 문자열 형태로 반환한다."""
if self.text[:] > self.text[:50]:
return self.text[:50] + "..."
else:
return self.text[:]
我的/learning_logs/views.py看起来像这样:
My /learning_logs/views.py looks like this:
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, Http404
from django.urls import reverse
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
from django.contrib.auth.decorators import login_required
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
def index(request):
"""학습 로그 홈페이지"""
return render(request, 'learning_logs/index.html')
@login_required
def topics(request):
"""주제를 표시한다."""
topics = Topic.objects.filter(owner=request.user).order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
@login_required
def topic(request, topic_id):
"""주제 하나와 연결된 모든 항목을 표시한다."""
topic = get_object_or_404(Topic, id=topic_id)
# 주제가 현재 사용자의 것인지 확인한다.
check_user = check_topic_owner(request, topic)
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):
"""새 주제 추가"""
if request.method != 'POST':
# 들어온 데이터가 없을 때는 새 폼을 만든다.
form = TopicForm()
else:
# POST 데이터를 받아서 처리한다.
form = TopicForm(request.POST)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user
new_topic.save()
return HttpResponseRedirect(reverse('learning_logs:topics'))
context = {'form': form}
return render(request, 'learning_logs/new_topic.html', context)
@login_required
def new_entry(request, topic_id):
"""특정 주제에 관한 새 항목을 추가"""
topic = get_object_or_404(Topic, id=topic_id)
check_user = check_topic_owner(request, topic)
if request.method != 'POST':
# 전송된 데이터가 없으므로 빈 폼을 만든다.
form = EntryForm()
else:
# 받은 POST 데이터를 처리한다.
form = EntryForm(data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.topic = topic
new_entry.save()
return HttpResponseRedirect(reverse('learning_logs:topic',
args=[topic_id]))
context = {'topic':topic, 'form':form}
return render(request, 'learning_logs/new_entry.html', context)
@login_required
def edit_entry(request, entry_id):
"""기존 항목을 편집한다."""
entry = get_object_or_404(Entry, id=entry_id)
topic = entry.topic
check_user = check_topic_owner(request, topic)
if request.method != 'POST':
# 첫 요청이므로 폼을 현재 텍스트로 채운다.
form = EntryForm(instance=entry)
else:
# POST 데이터를 받았으므로 받은 데이터를 처리한다.
form = EntryForm(instance=entry, data=request.POST)
return HttpResponseRedirect(reverse('learning_logs:topic',
args=[topic.id]))
context = {'entry': entry, 'topic':topic, 'form': form}
return render(request, 'learning_logs/edit_entry.html', context)
def check_topic_owner(request, topic):
"""현재 유저가 올바른 유저인지 체크한다"""
if topic.owner != request.user:
raise Http404
我的/learning_logs/forms.py看起来像这样
My /learning_logs/forms.py looks like this
from django import forms
from .models import Topic, Entry
class TopicForm(forms. ModelForm):
class Meta:
model = Topic
fields = ['text', 'public']
lavels = {'text' : '', 'public' : 'lavel for public'}
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})}
labels = {'text':''}
widgets = {'text': forms.Textarea(attrs={'cols':80})}
我的/learning_logs/templates/learning_logs/new_topic.html
My /learning_logs/templates/learning_logs/new_topic.html
{% extends "learning_logs/base.html" %}
{% load bootstrap3 %}
{% block header %}
<h2>Add a new topic:</h2>
{% endblock %}
{% block content %}
<form action="{% url 'learning_logs:new_topic' %}" method='post'
class="form">
{% csrf_token %}
{% bootstrap_form form %}
<div class="form-check">
<input type="checkbox" class="form-check-input" value=True id="public" />
<label class="form-check-label">
Make it public?
</label>
</div>
{% buttons %}
<button name="submit" class="btn btn-primary">add topic</button>
{% endbuttons %}
</form>
{% endblock %}
另一个错误:
如果删除@login_required,则会出现以下错误:
If I delete @login_required I get the following error:
Traceback:
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
126. response = self.process_exception_by_middleware(e, request)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
124. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/mnt/c/Users/heoje/Desktop/linked/learning_log/learning_logs/views.py" in topics
31. topics = Topic.objects.filter(owner=request.user).order_by('date_added')
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/manager.py" in manager_method
82. return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/query.py" in filter
844. return self._filter_or_exclude(False, *args, **kwargs)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/query.py" in _filter_or_exclude
862. clone.query.add_q(Q(*args, **kwargs))
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in add_q
1263. clause, _ = self._add_q(q_object, self.used_aliases)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in _add_q
1287. split_subq=split_subq,
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in build_filter
1198. self.check_related_objects(join_info.final_field, value, join_info.opts)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in check_related_objects
1065. for v in value:
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/utils/functional.py" in inner
214. return func(self._wrapped, *args)
Exception Type: TypeError at /topics/
Exception Value: 'AnonymousUser' object is not iterable
第二个错误
我使用了以下代码:
# this should really be a method on a custom ModelManager
def _get_topics_for_user(user):
" returns a queryset of topics the user can access "
q = Q(public=True)
# if django < 1.10 you want "user.is_authenticated()" (with parens)
if user.is_authenticated:
# adds user's own private topics to the query
q = q | Q(private=True, owner=user)
return Topic.objects.filter(q)
def topics(request):
topics = _get_topics_for_user(request.user).order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
def topic(request, topic_id):
topics = _get_topics_for_user(request.user)
# here we're passing the filtered queryset, so
# if the topic "topic_id" is private and the user is either
# anonymous or not the topic owner, it will raise a 404
topic = get_object_or_404(topics, id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)
Traceback:
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
126. response = self.process_exception_by_middleware(e, request)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
124. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/mnt/c/Users/heoje/Desktop/linked/learning_log/learning_logs/views.py" in topics
31. topics = _get_topics_for_user(request.user).order_by('date_added')
File "/mnt/c/Users/heoje/Desktop/linked/learning_log/learning_logs/views.py" in _get_topics_for_user
27. return Topic.objects.filter(q)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/manager.py" in manager_method
82. return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/query.py" in filter
844. return self._filter_or_exclude(False, *args, **kwargs)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/query.py" in _filter_or_exclude
862. clone.query.add_q(Q(*args, **kwargs))
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in add_q
1263. clause, _ = self._add_q(q_object, self.used_aliases)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in _add_q
1281. current_negated, allow_joins, split_subq)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in _add_q
1281. current_negated, allow_joins, split_subq)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in _add_q
1287. split_subq=split_subq,
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in build_filter
1164. lookups, parts, reffed_expression = self.solve_lookup_type(arg)
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in solve_lookup_type
1028. _, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
File "/mnt/c/Users/heoje/Desktop/linked/choco/lib/python3.6/site-packages/django/db/models/sql/query.py" in names_to_path
1389. "Choices are: %s" % (name, ", ".join(available)))
Exception Type: FieldError at /topics/
Exception Value: Cannot resolve keyword 'private' into field. Choices are: date_added, entry, id, owner, owner_id, public, text
您首先必须从 topics
和 topic
中删除 login_required
装饰器>视图,显然-顾名思义,此装饰器的目标是强制用户登录.
You first have to remove the login_required
decorator from the topics
and topic
views, obviously - the goal of this decorator, as the name implies, being to force users to log in.
然后,您必须更改视图代码以处理两种情况-匿名用户和登录用户.假设您希望每个人都可以看到公共主题,而只有主题所有者可以访问私有主题,则如下所示:
Then you have to change your views code to handle both cases - anonymous and logged in users. Assuming that you want everyone to see public topics and only topics owners to access private topics, this might look like this:
from django.db.models import Q
# this should really be a method on a custom ModelManager
def _get_topics_for_user(user):
" returns a queryset of topics the user can access "
q = Q(public=True)
# if django < 1.10 you want "user.is_authenticated()" (with parens)
if user.is_authenticated:
# adds user's own private topics to the query
q = q | Q(public=False, owner=user)
return Topic.objects.filter(q)
def topics(request):
topics = _get_topics_for_user(request.user).order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
def topic(request, topic_id):
topics = _get_topics_for_user(request.user)
# here we're passing the filtered queryset, so
# if the topic "topic_id" is private and the user is either
# anonymous or not the topic owner, it will raise a 404
topic = get_object_or_404(topics, id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)