有问题
我正在创建一个项目,您可以在其中创建主题,该主题对于未经身份验证的用户可以是私有的或公开的。然后,您可以在每个主题中输入多个条目,以应用于该主题。现在,我试图在我的new_topic.html中选中一个复选框,如果选中该复选框,它将计算为True,否则为False 但是如果没有登录我就看不到这个话题
我想要的
我想通过将视图中的公共属性更改为True来向尚未登录的用户显示公共主题,但是我不知道如何实现它们
我尝试过的事情
我玩过查询集topic.public == True 但我不知道该怎么用
代码
我的/learning_logs/modles.py看起来像这样:
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看起来像这样:
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看起来像这样
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
{% 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,则会出现以下错误:
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
答案 0 :(得分:0)
请勿使用login_required
装饰器,将要公开访问的视图上方的行@login_required
删除。
此login_required
装饰器用于确保只有经过身份验证的用户才能访问视图。
仅当您希望视图由已认证用户使用时才使用。
您会收到此错误,因为在Topic.objects.filter(owner=request.user)
行中,request.user
是AnonymousUser
。
如果仅当主题公开时才进行渲染,则可以使用topic.public
对其进行检查,如果它返回true或false,则代码可能类似于-
def topic(request, topic_id):
"""주제 하나와 연결된 모든 항목을 표시한다."""
topic = get_object_or_404(Topic, id=topic_id)
# 주제가 현재 사용자의 것인지 확인한다.
if topic.public:
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)
else:
return HttpResponseRedirect(reverse('access_dennined'))
根据需要使用@login_required
。
答案 1 :(得分:0)
首先,您必须从login_required
和topics
视图中删除topic
装饰器,显然-顾名思义,该装饰器的目标是强制用户登录
然后,您必须更改视图代码以处理两种情况-匿名用户和登录用户。假设您希望每个人都可以看到公共主题,而只有主题所有者可以访问私有主题,则如下所示:
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)