aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby <[email protected]>2022-09-18 23:04:46 -0400
committerBobby <[email protected]>2022-09-18 23:04:46 -0400
commit140331e3d9a5a411587f0a6a0d8fd6efc7fac1b2 (patch)
treef18f88bf78510bc9744d2bc394fac4af5fe5303f
parente385f75de7d3cf1499697115e86cbfbfc5e004a3 (diff)
downloadthatcomputerscientist-140331e3d9a5a411587f0a6a0d8fd6efc7fac1b2.tar.xz
thatcomputerscientist-140331e3d9a5a411587f0a6a0d8fd6efc7fac1b2.zip
Added New Post Page and Models
-rw-r--r--blog/admin.py1
-rw-r--r--blog/migrations/0001_initial.py63
-rw-r--r--blog/models.py54
-rw-r--r--blog_admin/urls.py4
-rw-r--r--blog_admin/views.py77
-rw-r--r--static/images/icons/formula.pngbin0 -> 2269 bytes
-rw-r--r--templates/blog_admin/edit_user.html2
-rw-r--r--templates/blog_admin/new_post.html243
-rw-r--r--templates/blog_admin/new_user.html2
-rw-r--r--templates/blog_admin/partials/posts_topbar.html13
-rw-r--r--templates/blog_admin/partials/users_topbar.html (renamed from templates/blog_admin/partials/main_section.html)2
-rw-r--r--templates/blog_admin/posts.html7
-rw-r--r--templates/blog_admin/users.html2
13 files changed, 456 insertions, 14 deletions
diff --git a/blog/admin.py b/blog/admin.py
index 8c38f3f3..20e8239f 100644
--- a/blog/admin.py
+++ b/blog/admin.py
@@ -1,3 +1,4 @@
from django.contrib import admin
# Register your models here.
+from .models import Post, Comment, Category, Tag
diff --git a/blog/migrations/0001_initial.py b/blog/migrations/0001_initial.py
new file mode 100644
index 00000000..fd8234e6
--- /dev/null
+++ b/blog/migrations/0001_initial.py
@@ -0,0 +1,63 @@
+# Generated by Django 4.0.6 on 2022-09-19 00:31
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Category',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=50)),
+ ('slug', models.SlugField(unique=True)),
+ ('description', models.TextField(blank=True)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Tag',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=50)),
+ ('slug', models.SlugField(unique=True)),
+ ('description', models.TextField(blank=True)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Post',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(max_length=100)),
+ ('slug', models.SlugField(max_length=100, unique=True)),
+ ('body', models.TextField()),
+ ('date', models.DateTimeField(auto_now_add=True)),
+ ('is_public', models.BooleanField(default=False)),
+ ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='blog.category')),
+ ('tags', models.ManyToManyField(blank=True, to='blog.tag')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Comment',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('body', models.TextField()),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('edited', models.BooleanField(default=False)),
+ ('edited_at', models.DateTimeField(blank=True, null=True)),
+ ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='blog.post')),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/blog/models.py b/blog/models.py
index 71a83623..00a8d782 100644
--- a/blog/models.py
+++ b/blog/models.py
@@ -1,3 +1,57 @@
from django.db import models
+from django.conf import settings
# Create your models here.
+class Category(models.Model):
+ name = models.CharField(max_length=50)
+ slug = models.SlugField(unique=True)
+ description = models.TextField(blank=True)
+ created_at = models.DateTimeField(auto_now_add=True)
+
+ def __str__(self):
+ return self.name
+
+class Tag(models.Model):
+ name = models.CharField(max_length=50)
+ slug = models.SlugField(unique=True)
+ description = models.TextField(blank=True)
+ created_at = models.DateTimeField(auto_now_add=True)
+
+ def __str__(self):
+ return self.name
+
+class Post(models.Model):
+ title = models.CharField(max_length=100)
+ slug = models.SlugField(max_length=100, unique=True)
+ body = models.TextField()
+ date = models.DateTimeField(auto_now_add=True)
+ author = models.ForeignKey(
+ settings.AUTH_USER_MODEL,
+ on_delete=models.CASCADE,
+ )
+ category = models.ForeignKey(
+ 'Category',
+ on_delete=models.CASCADE,
+ )
+ tags = models.ManyToManyField('Tag', blank=True)
+ is_public = models.BooleanField(default=False)
+
+ def __str__(self):
+ return self.title
+
+class Comment(models.Model):
+ post = models.ForeignKey(
+ 'Post',
+ on_delete=models.CASCADE,
+ )
+ user = models.ForeignKey(
+ settings.AUTH_USER_MODEL,
+ on_delete=models.CASCADE,
+ )
+ body = models.TextField()
+ created_at = models.DateTimeField(auto_now_add=True)
+ edited = models.BooleanField(default=False)
+ edited_at = models.DateTimeField(blank=True, null=True)
+
+ def __str__(self):
+ return self.body
diff --git a/blog_admin/urls.py b/blog_admin/urls.py
index 2862db88..c47fb9cf 100644
--- a/blog_admin/urls.py
+++ b/blog_admin/urls.py
@@ -5,11 +5,13 @@ app_name = 'blog-admin'
urlpatterns = [
path('users', views.users, name='users'),
path('users/new', views.new_user, name='new-user'),
+ path('users/search', views.users_search, name='users-search'),
path('users/<int:user_id>/edit', views.edit_user, name='edit-user'),
path('posts', views.posts, name='posts'),
+ path('posts/new', views.new_post, name='new-post'),
+ path('posts/search', views.posts_search, name='posts-search'),
path('comments', views.comments, name='comments'),
path('categories', views.categories, name='categories'),
path('tags', views.tags, name='tags'),
path('new', views.new, name='new'),
- path('search', views.search, name='search'),
] \ No newline at end of file
diff --git a/blog_admin/views.py b/blog_admin/views.py
index e3de1847..8ea2f815 100644
--- a/blog_admin/views.py
+++ b/blog_admin/views.py
@@ -2,25 +2,70 @@ from django.shortcuts import render, redirect
from users.models import UserProfile
from django.contrib.auth.models import User
from django.contrib import messages
+from blog.models import Post, Category, Tag
# Create your views here.
-def users(request):
+
+def posts(request):
if request.user.is_authenticated and (request.user.is_superuser or request.user.is_staff):
page = request.GET.get('page') if request.GET.get('page') else 1
try:
page = int(page)
except:
page = 1
- users = User.objects.filter(is_superuser=False)[(page-1)*50:page*50]
- num_pages = User.objects.filter(is_superuser=False).count() // 50 + 1
- print(num_pages)
- url_to_render = 'blog_admin/users.html?page={}'.format(page) if int(page) and int(page) > 1 else 'blog_admin/users.html'
- return render(request, url_to_render, { 'title': 'Manage Users', 'normal_users': users, 'num_pages': num_pages, 'page': page })
+ posts = Post.objects.all()[(page-1)*50:page*50]
+ num_pages = Post.objects.all().count() // 50 + 1
+ url_to_render = 'blog_admin/posts.html?page={}'.format(page) if int(page) and int(page) > 1 else 'blog_admin/posts.html'
+ return render(request, url_to_render, { 'title': 'Manage Posts', 'posts': posts, 'num_pages': num_pages, 'page': page })
else:
return redirect('blog:home')
-def posts(request):
- pass
+def posts_search(request):
+ q = request.GET.get('q')
+ if request.user.is_authenticated and (request.user.is_superuser or request.user.is_staff):
+ if q:
+ try:
+ # Get the posts where title or body or author or category or tags or slug contains q or the post id is int(q)
+ posts = Post.objects.filter(title__icontains=q) | Post.objects.filter(body__icontains=q) | Post.objects.filter(author__username__icontains=q) | Post.objects.filter(category__name__icontains=q) | Post.objects.filter(tags__name__icontains=q) | Post.objects.filter(slug__icontains=q) | Post.objects.filter(id = int(q))
+ except:
+ # Get the posts where title or body or author or category or tags or slug contains q
+ posts = Post.objects.filter(title__icontains=q) | Post.objects.filter(body__icontains=q) | Post.objects.filter(author__username__icontains=q) | Post.objects.filter(category__name__icontains=q) | Post.objects.filter(tags__name__icontains=q) | Post.objects.filter(slug__icontains=q)
+
+ return render(request, 'blog_admin/posts.html', { 'title': 'Search Results for "{}"'.format(q), 'posts': posts })
+ else:
+ return redirect('blog-admin:posts')
+ else:
+ return redirect('blog:home')
+
+def new_post(request):
+ if request.user.is_authenticated and (request.user.is_superuser or request.user.is_staff):
+ if request.method == 'POST':
+ print(request.POST)
+ # title = request.POST.get('title')
+ # body = request.POST.get('body')
+ # category = request.POST.get('category')
+ # tags = request.POST.get('tags')
+ # slug = request.POST.get('slug')
+ # if title and body and category and tags and slug:
+ # try:
+ # category = Category.objects.get(slug = category)
+ # tags = tags.split(',')
+ # tags = [Tag.objects.get(slug = tag) for tag in tags]
+ # post = Post.objects.create(title = title, body = body, category = category, slug = slug, author = request.user)
+ # post.tags.set(tags)
+ # post.save()
+ # messages.success(request, 'Post created successfully!')
+ # return redirect('blog-admin:posts')
+ # except Exception as e:
+ # messages.error(request, 'Error: {}'.format(e), extra_tags='new_post_create_error', data = { 'title': title, 'body': body, 'category': category, 'tags': tags, 'slug': slug })
+ # return redirect('blog-admin:new-post')
+ # else:
+ # messages.error(request, 'Error: All fields are required!', extra_tags='new_post_create_error', data = { 'title': title, 'body': body, 'category': category, 'tags': tags, 'slug': slug })
+ # return redirect('blog-admin:new-post')
+ else:
+ return render(request, 'blog_admin/new_post.html', { 'title': 'New Post' })
+ else:
+ return redirect('blog:home')
def comments(request):
pass
@@ -34,7 +79,21 @@ def tags(request):
def new(request):
pass
-def search(request):
+def users(request):
+ if request.user.is_authenticated and (request.user.is_superuser or request.user.is_staff):
+ page = request.GET.get('page') if request.GET.get('page') else 1
+ try:
+ page = int(page)
+ except:
+ page = 1
+ users = User.objects.filter(is_superuser=False)[(page-1)*50:page*50]
+ num_pages = User.objects.filter(is_superuser=False).count() // 50 + 1
+ url_to_render = 'blog_admin/users.html?page={}'.format(page) if int(page) and int(page) > 1 else 'blog_admin/users.html'
+ return render(request, url_to_render, { 'title': 'Manage Users', 'normal_users': users, 'num_pages': num_pages, 'page': page })
+ else:
+ return redirect('blog:home')
+
+def users_search(request):
q = request.GET.get('q')
if request.user.is_authenticated and (request.user.is_superuser or request.user.is_staff):
if q:
diff --git a/static/images/icons/formula.png b/static/images/icons/formula.png
new file mode 100644
index 00000000..5f8c136c
--- /dev/null
+++ b/static/images/icons/formula.png
Binary files differ
diff --git a/templates/blog_admin/edit_user.html b/templates/blog_admin/edit_user.html
index be32f236..9b508e11 100644
--- a/templates/blog_admin/edit_user.html
+++ b/templates/blog_admin/edit_user.html
@@ -1,7 +1,7 @@
{% extends 'blog/partials/base.html' %} {% block content %}
<div class="main">
<section>
- {% include 'blog_admin/partials/main_section.html' %}
+ {% include 'blog_admin/partials/users_topbar.html' %}
<form action="{% url 'blog-admin:edit-user' edit_user.id %}" method="post">
{% csrf_token %}
<div class="form-group">
diff --git a/templates/blog_admin/new_post.html b/templates/blog_admin/new_post.html
new file mode 100644
index 00000000..069ef329
--- /dev/null
+++ b/templates/blog_admin/new_post.html
@@ -0,0 +1,243 @@
+{% extends 'blog/partials/base.html' %} {% block content %}
+<link
+ rel="stylesheet"
+ href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/monokai-sublime.min.css"
+/>
+<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet" />
+<style>
+ .ql-editor {
+ font-family: "Times New Roman", Times, serif;
+ }
+</style>
+<div class="main">
+ <section>
+ {% include 'blog_admin/partials/posts_topbar.html' %}
+ <div class="form-group">
+ <label for="title">Title</label>
+ <input
+ style="display: inline-block"
+ type="text"
+ class="form-control"
+ id="title"
+ name="title"
+ placeholder="Enter an Amazing Title"
+ value="{{ data.title }}"
+ />
+ </div>
+ <div class="form-group">
+ <label for="slug">Slug</label>
+ <input
+ style="display: inline-block"
+ type="text"
+ class="form-control"
+ id="slug"
+ name="slug"
+ placeholder="Enter an Amazing Slug"
+ value="{{ data.slug }}"
+ />
+ </div>
+ <div class="form-group">
+ <div id="toolbar-container">
+ <span class="ql-formats">
+ <button class="ql-header" value="1"></button>
+ <button class="ql-header" value="2"></button>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-bold"></button>
+ <button class="ql-italic"></button>
+ <button class="ql-underline"></button>
+ <button class="ql-strike"></button>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-blockquote"></button>
+ <button class="ql-code-block"></button>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-script" value="sub"></button>
+ <button class="ql-script" value="super"></button>
+ </span>
+
+ <span class="ql-formats">
+ <button class="ql-list" value="ordered"></button>
+ <button class="ql-list" value="bullet"></button>
+ </span>
+ <span class="ql-formats">
+ <select class="ql-align"></select>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-link"></button>
+ <button class="ql-image"></button>
+ <button class="ql-formula"></button>
+ {% load static %}
+ <button class="ql-formula-block">
+ <img
+ style="height: 32px; position: relative; top: -6px; left: 4px"
+ src="{% static 'images/icons/formula.png' %}"
+ alt="Block Formula"
+ />
+ </button>
+ </span>
+ <span class="ql-formats">
+ <button class="ql-clean"></button>
+ </span>
+ </div>
+ <div id="editor-container" style="height: 60vh"></div>
+ </div>
+ <div class="form-group">
+ <label for="tags">Tags</label>
+ <input
+ style="display: inline-block"
+ type="text"
+ class="form-control"
+ id="tags"
+ name="tags"
+ placeholder="Enter Tags"
+ value="{{ data.tags }}"
+ />
+ </div>
+ <div class="form-group">
+ <label for="category">Category</label>
+ <select class="form-control" id="category" name="category" style = "display: inline-block">
+ {% for category in categories %}
+ <option value="{{ category.slug }}" {% if category.slug == data.category %} selected {% endif %}>{{ category.name }}</option>
+ {% endfor %}
+ </select>
+ </div>
+ <div class="form-group" style="display: none;">
+ <textarea name="body" id="body" value="{{ data.body }}"></textarea>
+ </div>
+ <div class="form-group">
+ <button type="submit" class="btn btn-primary">Submit</button>
+ </div>
+ </section>
+</div>
+<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-svg.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
+<script src="https://cdn.quilljs.com/1.3.6/quill.min.js"></script>
+<script src="https://cdn.jsdelivr.net/gh/T-vK/DynamicQuillTools@master/DynamicQuillTools.js"></script>
+<script>
+ const Parchment = Quill.import("parchment");
+ const Delta = Quill.import("delta");
+ class MathjaxInline extends Parchment.Embed {
+ static create(value) {
+ const node = super.create(value);
+ if (typeof value === "string") {
+ node.innerHTML = "&#65279;" + this.tex2svg(value) + "&#65279;";
+ node.contentEditable = "false";
+ node.setAttribute("data-value", value);
+ }
+ return node;
+ }
+
+ static value(domNode) {
+ return domNode.getAttribute("data-value");
+ }
+
+ static tex2svg(latex) {
+ let MathJaxNode = document.createElement("DIV");
+ MathJaxNode.style.visibility = "hidden";
+ MathJaxNode.innerHTML = "\\(" + latex + "\\)";
+ document.body.appendChild(MathJaxNode);
+ MathJax.typeset();
+ let svg = MathJaxNode.innerHTML;
+ document.body.removeChild(MathJaxNode);
+ return svg;
+ }
+ }
+
+ class MathjaxBlock extends Parchment.Embed {
+ static create(value) {
+ const node = super.create(value);
+ if (typeof value === "string") {
+ node.innerHTML = "&#65279;" + this.tex2svg(value) + "&#65279;";
+ node.contentEditable = "false";
+ node.setAttribute("data-value", value);
+ }
+ return node;
+ }
+
+ static value(domNode) {
+ return domNode.getAttribute("data-value");
+ }
+
+ static tex2svg(latex) {
+ let MathJaxNode = document.createElement("DIV");
+ MathJaxNode.style.visibility = "hidden";
+ MathJaxNode.innerHTML = "\\[" + latex + "\\]";
+ document.body.appendChild(MathJaxNode);
+ MathJax.typeset();
+ let svg = MathJaxNode.innerHTML;
+ document.body.removeChild(MathJaxNode);
+ return svg;
+ }
+ }
+
+ // Set module properties
+ MathjaxInline.blotName = "mathjax-inline";
+ MathjaxInline.className = "ql-mathjax-inline";
+ MathjaxInline.tagName = "SPAN";
+ MathjaxBlock.blotName = "mathjax-block";
+ MathjaxBlock.className = "ql-mathjax-block";
+ MathjaxBlock.tagName = "DIV";
+
+ // Register the module
+ Quill.register(MathjaxInline);
+ Quill.register(MathjaxBlock);
+
+ function insertFormula(quill, block) {
+ var range = quill.getSelection();
+ var latex = prompt(
+ "Enter a LaTeX formula",
+ quill.getText(range) == "" ? "e=mc^2" : quill.getText(range)
+ );
+ quill.deleteText(range.index, range.length);
+ if (block) {
+ quill.insertEmbed(range.index, "mathjax-block", latex);
+ } else {
+ quill.insertEmbed(range.index, "mathjax-inline", latex);
+ }
+ quill.insertText(range.index + range.length + 1, " ");
+ quill.setSelection(range.index + range.length + 1);
+ }
+
+ var quill = new Quill("#editor-container", {
+ modules: {
+ syntax: true,
+ toolbar: {
+ container: "#toolbar-container",
+ handlers: {
+ formula: function () {
+ insertFormula(quill, false);
+ },
+ "formula-block": function () {
+ insertFormula(quill, true);
+ },
+ },
+ },
+ },
+ placeholder: "Compose an epic...",
+ theme: "snow",
+ });
+
+ // update body on text change
+ quill.on("text-change", function (delta, oldDelta, source) {
+ document.getElementById("body").value = quill.root.innerHTML;
+ });
+
+ function slugify(text) {
+ return text
+ .toString()
+ .toLowerCase()
+ .replace(/\s+/g, "-") // Replace spaces with -
+ .replace(/[^\w\-]+/g, "") // Remove all non-word chars
+ .replace(/\-\-+/g, "-") // Replace multiple - with single -
+ .replace(/^-+/, "") // Trim - from start of text
+ .replace(/-+$/, ""); // Trim - from end of text
+ }
+
+ // slugify title
+ document.getElementById("title").addEventListener("input", function () {
+ document.getElementById("slug").value = slugify(this.value);
+ });
+</script>
+{% endblock %}
diff --git a/templates/blog_admin/new_user.html b/templates/blog_admin/new_user.html
index fd195912..217018d2 100644
--- a/templates/blog_admin/new_user.html
+++ b/templates/blog_admin/new_user.html
@@ -1,7 +1,7 @@
{% extends 'blog/partials/base.html' %} {% block content %}
<div class="main">
<section>
- {% include 'blog_admin/partials/main_section.html' %}
+ {% include 'blog_admin/partials/users_topbar.html' %}
<form action="{% url 'blog-admin:new-user' %}" method="post">
{% csrf_token %}
<div class="form-group">
diff --git a/templates/blog_admin/partials/posts_topbar.html b/templates/blog_admin/partials/posts_topbar.html
new file mode 100644
index 00000000..41b899a1
--- /dev/null
+++ b/templates/blog_admin/partials/posts_topbar.html
@@ -0,0 +1,13 @@
+<h1 style="font-size: 2em;">{{ title }}</h1>
+<div class="float-right">
+ <a href="{% url 'blog-admin:new-post' %}" >Create New Post</a>
+ {% comment %} Search Users Box {% endcomment %}
+ <form style="display: inline-block; margin-left: 10px;" action="{% url 'blog-admin:posts-search' %}" method="get">
+ <input style="display: inline-block" type="text" name="q" placeholder="Search Posts" autocomplete="off"/>
+ <input style="display: inline-block" type="submit" value="Search" />
+ </form>
+</div>
+<hr>
+{% for message in messages %}
+ <p class="{{message.tags}}" style="text-align:center;">{{ message }}</p>
+{% endfor %} \ No newline at end of file
diff --git a/templates/blog_admin/partials/main_section.html b/templates/blog_admin/partials/users_topbar.html
index 8af4328c..0b3043ad 100644
--- a/templates/blog_admin/partials/main_section.html
+++ b/templates/blog_admin/partials/users_topbar.html
@@ -2,7 +2,7 @@
<div class="float-right">
<a href="{% url 'blog-admin:new-user' %}" >Create New User</a>
{% comment %} Search Users Box {% endcomment %}
- <form style="display: inline-block; margin-left: 10px;" action="{% url 'blog-admin:search' %}" method="get">
+ <form style="display: inline-block; margin-left: 10px;" action="{% url 'blog-admin:users-search' %}" method="get">
<input style="display: inline-block" type="text" name="q" placeholder="Search Users" autocomplete="off"/>
<input style="display: inline-block" type="submit" value="Search" />
</form>
diff --git a/templates/blog_admin/posts.html b/templates/blog_admin/posts.html
new file mode 100644
index 00000000..410d1aed
--- /dev/null
+++ b/templates/blog_admin/posts.html
@@ -0,0 +1,7 @@
+{% extends 'blog/partials/base.html' %} {% block content %}
+<div class="main">
+ <section>
+ {% include 'blog_admin/partials/posts_topbar.html' %}
+ </section>
+</div>
+{% endblock %}
diff --git a/templates/blog_admin/users.html b/templates/blog_admin/users.html
index 084198d7..8b69cd69 100644
--- a/templates/blog_admin/users.html
+++ b/templates/blog_admin/users.html
@@ -1,7 +1,7 @@
{% extends 'blog/partials/base.html' %} {% block content %}
<div class="main">
<section>
- {% include 'blog_admin/partials/main_section.html' %}
+ {% include 'blog_admin/partials/users_topbar.html' %}
<table class="table table-striped">
<thead>
<tr>