Chapter 3 Article Management and Display

Posted by vtroubled on Sat, 17 Aug 2019 08:03:03 +0200

Article Directory


There must be content in the website. At present, there are two kinds of content that can be classified according to the way content is generated. One is "User Generated Content (UGC)", such as "YouTube", "Twitter". The other is "Professional Produced Content (PGC/PPC)", such as "Learn from Lao Qi itdiffer.com".

3.1. Manage Article Items

Every user who publishes an article wants to use Columns to categorize his or her articles without cluttering his or her pages, as shown in the following image.

[External chain picture transfer failed (img-NSAUYKp3-1566021128514)(http://ox1o0eyh1.bkt.clouddn.com/18-1-16/42772690.jpg)]

3.1.1 Setup Columns

Before you can implement the article management function, it is necessary to create an "article management" application to distinguish the previous applications.

➜  mysite python manage.py startapp article

Create an application named article and configure it in. /mysite/settings.py.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
    'account',
	'password_reset',
	'article',
]

Then there are the steps we're already familiar with, creating data models, forms, view functions, front-end templates, and configuring URL s.After this series of operations is completed, the basic functional goals are achieved, which seems simple, but there are still many areas to be carefully implemented or knowledge and skills to be supplemented.

1. Column data model

For article columns, there are no multilevel settings, only one level columns (I do not recommend that users click one level at a time to find what they want), so the data model of the columns is slightly simpler.Edit the. /article/models.py file and enter the following code.

from django.db import models
from django.contrib.auth import User

# Create your models here.
class ArticleColumn(models.Model):
	user = models.ForeignKey(User, related_name='article_column')	#1
	column = models.CharField(max_length=200)
	created = models.DateField(auto_now_add=True)
	
	def __str__(self):
		return self.column

There is a "one-to-one" relationship between users and article columns, that is, a user can set up multiple article columns and achieve this relationship between ArticleColumn and User through statement 1.In Django, the relationships between model objects can be summarized as "one-to-one", "one-to-many" and "many-to-many", corresponding to OneToOneField, ForeignKey, ManyToManyField.Readers do not need to tangle with the deep connotations of the three for the time being, first follow the code provided in this book, and then wait until the subsequent knowledge increases to become known naturally.

Once the data model is built, the data is migrated and the database tables are generated (ask the reader to do this on his own; if you don't have a way to migrate the data, see the previous description in this book).

With a data model, you naturally need a form class, because to fill in the project name through the form, you assign a value to the column field.So create the. /article/forms.py file and write the following code.

from django import forms
from .models import ArticleColumn

class ArticleColumnForm(forms.ModelForm):
	class Meta:
		model = ArticleColumn
		fields = ("column",)

2. Simple View Functions

To get an intuitive sense of what's going to be done, let's write a simple view function instead of a form class for the moment, and see what we're going to achieve.

Convenient. /article/views.py file, enter the following information.

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from .models import ArticleColumn

# Create your views here.
@login_required(login_url="/account/login/")
def article_column(request):
	columns = ArticleColumn.objects.filter(user=request.user)	#1
	return render(request, "article/column/article_column.html", {"columns": columns})

In the article_column() function, two statements are essentially merged together, one is ArticleColumn.objects.all(), and then deleted according to the condition of user=request.user, that is, ArticleColumn.objects.all().filter(user=request.user). These two query behaviors can be used with statement 2.Like an instruction.

Next, configure the URL in. /mysite/urls.py.

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^blog/', include('blog.urls', namespace='blog', app_name='blog')),
    url(r'^account/', include('account.urls', namespace='account', app_name='account')),
	url(r'^pwd_reset/', include('password_reset.urls', namespace='pwd_reset', app_name='pwd_reset')),
	url(r'^article/', include('article.urls', namespace='article', app_name='article')),
]

Create a. /article/urls.py file to set the URL of this application.

from django.conf.urls import url
from . import views

urlpatterns = [
	url(r'^article-column/$', views.article_column, name="article_column"),
]

The next step is to write the front-end template, and everything proceeds in an orderly manner following the prescribed steps.

3. Front End Template

Now to achieve user management of their own article columns, for this management function, the author treats it as the so-called "background", that is, not displayed to all users, only local users can use it.So there are also changes in the display style.

Create an article directory in the. /templates directory, then create a. /templates/article/header.html file with the following code.

{% load staticfiles %}
<div class="container">
	<nav class="navbar navbar-default" role="navigation">
		<div class="navbar-header">
			<a class="navbar-brand" href="http://www.itdiffer.com">
				<img width="100px" src="{% static 'images/backlogo.png' %}">
			</a>
		</div>
		<div>
			<ul class="nav navbar-nav" role="tablist">
				<li><a href="{% url 'article:article_column' %}">Article Management</a></li>
			</ul>
			<ul class="nav navbar-nav navbar-right" style="margin-right:10px">
				<li><a href="{% url 'blog:blog_title' %}">Home</a></li>
				<li><span>{{ user.username }}</span></li>
				<li><a href="{% url 'account:user_logout'%}">Logout</a></li>
			</ul>
		</div>
	</nav>
</div>

Readers can look closely at the above code and see that it does not differ much from the. /templates/header.html source code.

Readers here should be able to imagine a process in which when a user logs in, to manage their own article columns, they have to go into the so-called "background", but where is the entrance?Therefore, you also need to set the entry for the logged-in user. The entry location is the same as the previously set "Modify Password" and "Personal Information", so modify the. /templates/header.html file to set the entry.Note that this page goes into the background through the entrance. The author chose the page that he is ready to do now, but of course he can also modify it to other pages.

<li><a href="{% url 'account:password_change' %}">Change Password</a></li>
<li><a href="{% url 'account:my_information' %}">Personal information</a></li>
<li><a href="{% url 'article:article_column' %}">Back-stage management</a></li>

Upload the code so that the reader can find the right place to put it.Certainly!I'm sure.

The footer.html file in the background section, you can continue to use. /templates/footer.html.

Normal management background, there is a function column on the left side, so let's do one.Create a. /templates/article/leftslider.html file with the following code.

<div class="bg-info">
	<div class="text-center" style="margin-top:5px;">
		<p><a href="{% url 'article:article_column' %}">Column Management</a></p>
	</div>
</div>

The following is the assembly of the. /templates/article/base.html file, coded as follows.

{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="X-UA-Compatible" content="IE=Edge">
	<meta charset="utf-8">
	<meta name="viewport" content="with=device-with, initial-scale=1">
	<title>{% block title %}{% endblock %}</title>
	<link rel="stylesheet" href="{% static 'css/bootstrap.css' %}">
</head>
<body>
<div class="container">
	{% include 'article/header.html' %}
	<div class="col-md-2">
		{% include 'article/leftslider.html'%}
	</div>
	<div class="col-md-10">
		{% block content %}
		{% endblock %}
	</div>
	{% include 'footer.html' %}
</div>
</body>
</html>

All of the above are preparations. You haven't written the template required for the view function yet!The. /templates/column/article_column.html file is created below, and the following code is entered.

{% extends "article/base.html" %}
{% load staticfiles %}
{% block title %}article column{% endblock %}
{% block content %}
<div>
	<p class="text-right">
		<button class="btn btn-primary">add column</button>
	</p>
	<table class="table table-hover">
	<tr>
		<td>Sequence Number</td>
		<td>Column Name</td>
		<td>operation</td>
	</tr>
	{% for column in columns %}
	<tr>
		<td>{{ forloop.counter }}</td>
		<td>{{ column.column }}</td>
		<td>--</td>
	</tr>
	{% empty %}
	<p>No columns set up yet. Too lazy</p>
	{% endfor %}
	</table>
</div>
{% endblock %}

Output of each row of data in the table is implemented as {% for column in columns%}.Forloop in {forloop.counter}} only works inside a loop. It is a template variable with properties that indicate the progress of the loop. For example, here the effect of forloop.counter is used to get the sequence number of each loop, which is essentially a counter that shows the current number of loops (so start from 1).If the variable columns references an empty object, the following is executed through {% empty%}.{% empty%} in the loop statement omits if judgment.

Once the template is ready, run the Django service and type http://localhost:8000/article/article-column/ in the browser's address bar. If the user is not logged in, he or she jumps to the login page and sees the effect as shown in the following figure.

The following modifications have been made here for the sake of aesthetics.

{% load staticfiles %}
<div class="container">
	<nav class="navbar navbar-default" role="navigation">
		<div class="navbar-header">
			<a class="navbar-brand" href="http://www.itdiffer.com">
				<img width="100px" src="{% static 'images/backlogo.png' %}">
			</a>
		</div>
		<div>
			<ul class="nav navbar-nav" role="tablist">
				<li><a href="{% url 'article:article_column' %}">Article Management</a></li>
			</ul>
			<ul class="nav navbar-nav navbar-right" style="margin-right:10px">
				<li><a href="{% url 'blog:blog_title' %}">Home</a></li>
				
				<li>
					<div class="dropdown" style="margin-top:8px">
						<button class='btn btn-default dropdown-toggle' type='button' id='dropdownMenu' data-toggle='dropdown'>
						{{ user.username }}<span class='caret'></span>
						</button>
						<ul class="dropdown-menu">
							<li><a href="{% url 'account:password_change' %}">Change Password</a></li>
							<li><a href="{% url 'account:my_information' %}">Personal information</a></li>
						</ul>
					</div>
				</li>
				<li><a href="{% url 'account:user_logout' %}">Logout</a></li>
			</ul>
		</div>
	</nav>
</div>

<script src="{% static 'js/jquery.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>

[External chain picture transfer failed (img-QDcVsaLK-1566021128515)(http://ox1o0eyh1.bkt.clouddn.com/18-1-17/43756499.jpg)]

At present, this user has not set any columns, so it is the display effect above.If you want to see the effect of the column, you can first add several pieces of data to the database using Firefox's SQLLite Manager tool, because the "add column" function in the top corner of the page has not been done yet.

Adding data directly to the database is entirely for testing purposes and should be absolutely prohibited in a real website project.

After adding the data, refresh the page as shown in the following image.

The effect of this interface is to list the existing column names. Although the layout of each element is a bit simple, you can see the expected effect after all.The next step is now clear and new columns will be added.

4. Add new columns

The process of adding a new column is to click the add column button to bring up a dialog box in which you can enter a new column name.

For pop-up dialogs, use the layer.js plug-in used in chapter 2.Edit the. /templates/article/column/article_column.html file and modify the original <button>appropriately with the following code.

<button id="add_column" onclick="add_column()" class="btn btn-primary">add column</button>

When the user clicks this button, the add_column() function (JavaScript function) is triggered with the following code (the following code is at the end of the file {% endblock%}).Reminds the reader that this method of binding JavaScript functions to HTML is not advocatable in real projects. The projects in this book are mainly about learning Django, so for ease of reading and understanding, there is no separation of coding. Please note.

<script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
<script type="text/javascript" src="{% static 'js/layer.js' %}"></script>
<script type="text/javascript">
function add_column() {
	var index = layer.open({
		type: 1,
		skin: "layui-layer-rim",
		area: ["400px", "200px"],
		title: "New Columns",
		content: '<div class="text-center" style="margin-top:20px"><p>Please enter a new column name</p><p><input type="text"></p></div>',
		btn: ['Determine', 'cancel'],
		yes: function(index, layero) {
			column_name: $('#id_column').val();
			alert(column_name);
		},
		btn2: function(index, layero) {
			layer.close(index);
		}
	});
}
</script>

In the added code, it is necessary to introduce jQuery and layer. Focus on the add_column() function. In the dialog box that pops up, Statement 1 is for the first OK button, where we only get the name of the column we wrote.Statement is for the second Cancel button.

Look at the effect first, though it's the front end, it hasn't sent data to the back end yet.Click the add column button, as shown below.

[External chain picture transfer failed (img-ZEf0Kyh0-1566021128516)(http://ox1o0eyh1.bkt.clouddn.com/18-1-17/18318480.jpg)]

It's just an effect. To achieve real business, you need to continue to improve the back-end code.

Edit the. /article/views.py file, override the article_column() view function, and here's all the code.

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse

from .models import ArticleColumn
from .forms import ArticleColumnForm

# Create your views here.
@login_required(login_url="/account/login/")
@csrf_exempt
def article_column(request):
    if request.method == 'GET':
        columns = ArticleColumn.objects.filter(user=request.user)
        column_form = ArticleColumnForm()
	    return render(request, "article/column/article_column.html", {"columns": columns, "column_form": column_form})

    if request.method == 'POST':
        column_name = request.POST['column']
        columns = ArticleColumn.objects.filter(user_id=request.user.id, column=column_name)

        if columns:
            return HttpResponse("2")
        else:
            ArticleColumn.objects.create(user=request.user, column=column_name)
            return HttpResponse("1")

Topics: Django Javascript Database JQuery