You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django为超级管理员开放所有分支论坛访问权限的实现方案

问题描述
  • 已实现支持动态分支分配的讨论论坛网站:普通用户注册时选择所属分支,登录后仅可查看自身所选分支下的帖子,普通用户侧功能运行正常
  • 超级管理员账号访问/forum路径时抛出报错:DoesNotExist at /forum Register matching query does not exist.
  • 报错根因明确:管理员账号未在Register模型中关联分支记录,但若给管理员绑定单个分支,会导致管理员仅能查看单分支帖子,无法满足查看全部分支帖子的管理需求
项目核心代码

model.py

Post模型

class Post(models.Model):
user1 = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
post_id = models.AutoField
post_content = models.TextField(max_length=5000,verbose_name="")
timestamp= models.DateTimeField(default=now)
branch=models.CharField(default='',max_length=200)
image = models.ImageField(upload_to="images",default="")
def __str__(self):
   return f'{self.user1} Post'

Reply模型

class Replie(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
reply_id = models.AutoField
reply_content = models.TextField(max_length=5000,verbose_name="")
post = models.ForeignKey(Post, on_delete=models.CASCADE, default='')
timestamp= models.DateTimeField(default=now)
image = models.ImageField(upload_to="images",default="")
def __str__(self):
   return f'{self.user1} Post'

用户注册关联模型

class Register(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
branch= models.CharField(max_length=100)
def __str__(self):
   return self.user.username

view.py

forum视图逻辑(原代码)

def forum(request):
user = request.user
profile = Profile.objects.all()
user = User.objects.get(id=request.user.id)
data = Register.objects.get(user = user)
user_posts = Post.objects.filter(branch=data.branch).count()
if request.method=="POST":   
      user = request.user
      image = request.user.profile.image
      content = request.POST.get('content','')
      branch = request.POST.get('branch','')
      title = request.POST.get('title','')
      post = Post(user1=user, post_content=content, image=image,branch=branch,title=title)
      post.save()
      messages.success(request, f'Your Question has been posted successfully!!')
      return redirect('/forum') 
posts = Post.objects.filter(branch=data.branch).order_by('-timestamp')
print(data.branch)
context={
'posts':posts,
    'branch':data.branch,
    'user_posts':user_posts
}
return render(request, "forum.html",context)

forum.html

{% if user.is_superuser or user.is_staff %}
{% include "instructor/admin_nav.html" %}
{% else %}
 {% include "user/user_nav.html" %}
{% endif %}
{% block body %}
<div class="container my-4 ">
<div class="jumbotron"style="margin-bottom: 5%;    text-align: center;">
{% if user.is_superuser or user.is_staff %}
 <h3 class="display-4 font"> Disscussion Forum</h3>
<center class="lead post">Welcome to our discussion forum. You can post your question or any related queries by simply clicking on the add post button.</center>
<hr class="my-4 hr1">
<p class="post">You can also reply to others post by clicking on add or see reply button.</p>
{% else %}
 <h1 class="font mt-0"> {{branch}}   Disscussion Forum</h1>
<center >Welcome to  discussion forum. You can post your question or any related queries by simply clicking on the add post button.</center>
  <p>You can also reply to others post by clicking on add or see reply button.</p>
  <hr class="my-4 h">
<small>keep all posts on the topic. 
Any posts deemed to be in the wrong category will be removed.</small><br>
{% endif %}
<button class="btn btn-primary btn-lg text bluebtn" data-target="#questions" data-toggle="modal" role="button">Add Post</button>
<form class="form-inline my-2 my-lg-0">
  <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
  <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
{% if user_posts == 0 %}
<div class="jumbotron">
 <h4 class="display-4">No Results fountd</h4>
<p class="lead">Be the first person to ask question</p>
</div>
{% endif %}
{% for post in posts %}
<div class="container-fluid mt-10">
  <div class="row">
      <div class="col-md-12">
          <div class="card mb-4 forumcardcss">
              <div class="card-header forumcardheader">
                  <div class="media flex-wrap w-100 align-items-center imgcss"> <img src="/media/{{post.image}}" 
                          class="d-block ui-w-40 rounded-circle" alt="profileimage"style="width: 40px;height: 40px;">  <p class="ml-4 usernamecss">  {{post.user1}} </p>
                       <div class="media-body ml-3">
                      </div>
 <div class="text-muted small ml-3">
                        <div class="px-4 pt-3 f" >  {{post.timestamp}} </div>
                      </div>
                       {% if user.is_superuser or user.is_staff %}
                        <a href="{% url 'dashboard:delete_post' post.id %}"> <button class="btn btn-danger btn-sm text" onclick="window.mytest()"style="background-color: #e60000;">Delete</button></a>
                        <script type="text/javascript">window.mytest = function() { var isValid = confirm('If you click ok then its delete this post and related reply on it. Are you sure to delete?');if (!isValid) { event.preventDefault();  alert("It wont delete. Yay!");}}</script>
                        {% endif %}
                      </div>
                   </div>         
               <div class="card-body forumcardbody">
                  <p class="text">{{ post.post_content|linebreaks|truncatewords_html:10 }}</p>{% if post.post_content|length|get_digit:"-1" > 50 %} 
               <a href="/discussion/{{post.id}}" data-abc="true"><button class="btn btn-light text" style="color:blue; font-size: 13px;">Show more </button>  </a>
             {% endif %}
            </div>
          </div>
          </div>
      </div>
  </div>
{% endfor %}
</div>

<!-- Modal -->
<div class="modal fade" id="questions" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
  <div class="modal-content">
    <div class="modal-header">
  

<h5 class="modal-title" id="exampleModalLabel"></h5>
      <button type="button" class="close" data-dismiss="modal" aria-label="Close">
        <span aria-hidden="true">&times;</span>
      </button>
</div>
 {% if user.is_authenticated %}
    <div class="modal-body">
      <form action="/forum" method="POST">
     {% csrf_token %}
  <div class="form-group">
<label style="font-size:1rem; font-weight:bold;">Post Your Question Here</label>

<textarea class="form-control" id="content" name="content" rows="3"></textarea>
      </div>
    </div>
    {% else %}
    <h3>Please Login to post</h3>
    {% endif %}
    <div class="modal-footer">
      <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
      <button type="submit" class="btn btn-primary">Post</button>
</div>
  </div>
</div>
 </div>
 </div>

 {% endblock body %}

urls.py

app_name = "dashboard"
urlpatterns = [

    path('', views.index, name="index"),
    path('user_home', views.user_home, name="user_home"),
    path('admin_home', views.admin_home, name="admin_home"),
    path("forum", views.forum, name="forum"),
    path("discussion/<int:myid>", views.discussion, name="discussion"),
    path("showallusers", views.show_all_users, name="showallusers"),
    path('delete_user/<int:pk>', views.delete_user, name="delete_user"),
    path('delete_post/<int:pk>', views.delete_post, name="delete_post"),
    path('delete_reply/<int:pk>', views.delete_reply, name="delete_reply"),
    path('upload_notes', views.upload_notes, name='upload_notes'),
    path('view_mynotes', views.view_mynotes, name='view_mynotes'),
    path('delete_mynotes/<int:pk>/', views.delete_mynotes, name='delete_mynotes'), 
    path('pending_notes', views.pending_notes, name='pending_notes'),
    path('assign_status/<int:pk>', views.assign_status, name='assign_status'),
    path('accepted_notes', views.accepted_notes, name='accepted_notes'),
    path('rejected_notes', views.rejected_notes, name='rejected_notes'),
    path('all_notes', views.all_notes, name='all_notes'),
    path('delete_notes/<int:pk>', views.delete_notes, name='delete_notes'),
    path('delete-records/', views.delete_notes, name='delete_notes'),
    path('view_allnotes', views.view_allnotes, name='view_allnotes'),
    path('notessharing', views.notessharing, name='notessharing'),
    path('edit_post/<int:pk>/', views.edit_post, name='edit_post'),
    path('edit_reply/<int:pk>/', views.edit_reply, name='edit_reply'),
]
实现方案

核心思路是在视图层增加用户身份分流逻辑,不需要修改现有模型结构,不需要给管理员账号绑定Register分支记录,完全基于Django自带的超级管理员/职员权限标识做逻辑拆分,改动量最小,不影响现有普通用户功能。

1. 修改forum视图逻辑

替换原有直接查询Register表的逻辑,先判断用户身份,管理员走全量数据查询,普通用户走原有分支过滤逻辑,同时增加异常兜底,避免普通用户未绑定分支时报错。修改后的代码如下:

def forum(request):
    user = request.user
    profile = Profile.objects.all()
    # 标记当前用户是否为管理员
    is_admin = user.is_superuser or user.is_staff
    user_posts = 0
    current_branch = ""
    posts = Post.objects.none()

    if is_admin:
        # 管理员逻辑:查询全部分支帖子
        posts = Post.objects.all().order_by('-timestamp')
        user_posts = posts.count()
        current_branch = "全部分支"
    else:
        # 普通用户逻辑:查询所属分支帖子
        try:
            data = Register.objects.get(user=user)
            current_branch = data.branch
            posts = Post.objects.filter(branch=current_branch).order_by('-timestamp')
            user_posts = posts.count()
        except Register.DoesNotExist:
            # 普通用户未绑定分支的兜底处理,可替换为自己的分支选择页路径
            messages.error(request, "请先绑定所属分支后再访问论坛")
            return redirect('/user_home')

    if request.method=="POST":   
        user = request.user
        image = request.user.profile.image
        content = request.POST.get('content','')
        branch = request.POST.get('branch','')
        title = request.POST.get('title','')
        # 普通用户发帖强制使用自身所属分支,避免前端参数篡改
        if not is_admin:
            branch = current_branch
        post = Post(user1=user, post_content=content, image=image,branch=branch,title=title)
        post.save()
        messages.success(request, f'Your Question has been posted successfully!!')
        return redirect('/forum') 

    context={
        'posts':posts,
        'branch':current_branch,
        'user_posts':user_posts,
        'is_admin':is_admin
    }
    return render(request, "forum.html",context)

2. 适配模板逻辑

原有模板已经做了管理员导航、普通用户导航的区分,只需要补充两个小适配:

  • 在发帖模态框的表单中增加分支选择逻辑:管理员显示分支选择下拉框,普通用户隐藏分支选择,通过隐藏域传递自身分支值,示例代码如下:
<form action="/forum" method="POST">
    {% csrf_token %}
    <div class="form-group">
    <label style="font-size:1rem; font-weight:bold;">Post Your Question Here</label>
    <textarea class="form-control" id="content" name="content" rows="3"></textarea>
    </div>
    <!-- 新增分支选择逻辑 -->
    {% if is_admin %}
    <div class="form-group">
        <label style="font-size:1rem; font-weight:bold;">所属分支</label>
        <select class="form-control" name="branch" required>
            <!-- 替换为实际的分支选项,也可从视图传分支列表遍历生成 -->
            <option value="分支A">分支A</option>
            <option value="分支B">分支B</option>
        </select>
    </div>
    {% else %}
    <input type="hidden" name="branch" value="{{branch}}">
    {% endif %}
</form>
  • 可选优化:在帖子卡片的用户名旁增加分支标签,管理员视角下可直接看到每个帖子所属分支,示例代码:
<p class="ml-4 usernamecss">  {{post.user1}} </p>
{% if is_admin %}
<span class="badge badge-info ml-2">{{post.branch}}</span>
{% endif %}

注意事项

项目中其他涉及Register.objects.get(user=user)查询的视图(比如帖子详情页discussion、回复相关逻辑),都需要增加同样的管理员身份判断,避免其他页面抛出相同的DoesNotExist报错。


内容的提问来源于stack exchange,提问作者Ajay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 02:18:15