There’s usually more than one type of blog post: sometimes you’ll write incomprehensible technical posts, and sometimes you’ll just write about the mood of the day.

Therefore, the classification of articles is quite important, which is convenient for bloggers to classify and archive articles, and also convenient for users to have targeted reading.

An important way to classify articles is to set up columns.

Column model

There are many ways to realize the function of article column. You can simply add the CharField() field to the article’s Model and store the column name as a string (in reality, this implementation is more like ** “tags” **, more on that later). This has the advantage of being simpler; The disadvantages are obvious: you may get confused with column names over time, and it is not convenient to expand other attributes of the column.

Therefore, the column of the article can be an independent Model, with foreign keys associated with the Model of the article.

Modify article/modles.py:

article/models.py

...

class ArticleColumn(models.Model):
    """ The Model of the column ""
    # Column title
    title = models.CharField(max_length=100, blank=True)
    # create time
    created = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.title


class ArticlePost(models.Model):.# "one to many" foreign key in the article column
    column = models.ForeignKey(
        ArticleColumn,
        null=True,
        blank=True,
        on_delete=models.CASCADE,
        related_name='article')...Copy the code

The column’s Model has two fields, Name and Creation date.

An article has only one column, and a column can correspond to multiple articles, so a one-to-many relationship is established.

After writing the model, use Hoisting and Migrate commands to migrate data.

Displays columns in the list

Adding test Data

Once the model is written, several columns of data are needed to test it. Since you haven’t written a view yet, you need to make good use of Django’s built-in backend.

First register the column model in the background:

article/admin.py

...

from .models import ArticleColumn

# Sign up for the articles column
admin.site.register(ArticleColumn)
Copy the code

Then you can add the column’s data entry in the background:

I added HTML, Java, and Django at random.

Open a random article in the background, and the column field is waiting for you quietly:

Randomly select several articles and set different columns for testing.

Rewrite article list

Earlier we used a card-type UI to present the list of articles.

The advantage of cards is that they are simple and elegant, but as the amount of data increases, the small size of the cards becomes overwhelmed.

So here’s rewriting the list loop for the list.html template:

article/list.html

...

<! -- List loop -->
<div class="row mt-2">
    {% for article in articles %}
        <! -->
        <div class="col-12">
            <! - section - >
            {% if article.column %}
                <button type="button" 
                    class="btn btn-sm mb-2 {% if article.column.title == 'Django' %} btn-success {% elif article.column.title == 'Java' %} btn-danger {% elif article.column.title == 'HTML' %} btn-warning {% endif %} "
                >
                    {{ article.column }}
                </button>
            {% endif %}
            <! - the title -- -- >
            <h4>
                <b>
                    <a href="{% url 'article:article_detail' article.id %}"
                       style="color: black;" 
                    >
                        {{ article.title }}
                    </a>
                </b>
            </h4>
            <! -- -- -- > the
            <div>
                <p style="color: gray;">
                    {{ article.body|slice:'100' }}...
                </p>
            </div>
            <! - the footnote - >
            <p>
                <! -- Additional information -->
                <span style="color: green;">{{article. Total_views}} browse &nbsp; &nbsp; &nbsp;</span>
                <span style="color: blue;">{{article. Created | date: 'Y -m - d'}} release & have spent &nbsp; &nbsp;</span>
                <span style="color: darkred;">{{article. Updated | date: 'Y -m - d'}} update</span>
            </p>
            <hr>
        </div>
    {% endfor %}
</div>.Copy the code

The main change is the addition of a “column” button. We even have different button colors for different columns.

In the additional information, the date information that was not used before has also been added.

Take a look at the results:

It feels good!

Modify the write article function

Presentation is fine, but you can’t select columns when publishing new articles.

Modify the template for writing an article by adding the following content to the form:

templates/article/create.html

...

<! -- Form for submitting articles -->
<form method="post" action=".">
    {% csrf_token %}
    <! -- Article title -->.<! -- Article column -->
    <div class="form-group">
        <label for="column">The column</label>
        <select class="form-control" 
                id="column" 
                name="column"
        >
                <option value="none">Please select column..</option>
            {% for column in columns %}
                <option value="{{ column.id }}">{{ column }}</option>
            {% endfor %}
        </select>
    </div>

    <! -- Text -->.<! -- Submit button -->.</form>
Copy the code

< SELECT > is the drop-down selection component of the form. In this component, loop through all the column data and set the value property to specify the ID value of the form submission column.

Refresh the page like this:

As before, you can show it, but you don’t have the view logic to process the form.

Modify the existing write article view article_create() to handle column data for form uploads:

article/views.py

# Introduce column Model
from .models import ArticleColumn

...

# View for writing articles.def article_create(request):
    if request.method == "POST":...if article_post_form.is_valid():
            ...
            
            # New code
            if request.POST['column'] != 'none':
                new_article.column = ArticleColumn.objects.get(id=request.POST['column'])
            
            # Existing code
            new_article.save()
            ...
    else:...# New and modified code
        columns = ArticleColumn.objects.all()
        context = { 'article_post_form': article_post_form, 'columns': columns }
        
        ...
Copy the code

The new code involves two parts: GET and POST:

  • POST: The main consideration is that some articles can be columns free. So withifStatement determines whether the article has a column, and if so, submits according to the formvalueValue, associated with the corresponding column.
  • GET: Adds context to columns for use by templates.

To test this, the column function for writing articles should work properly.

Modify update view

The view for updating articles also needs to be updated.

Change the template first:

templates/article/update.html

...

<! -- Form for submitting articles -->
<form method="post" action=".">
    {% csrf_token %}

    <! -- Article title -->.<! -- Article column -->
    <div class="form-group">
        <label for="column">The column</label>
        <select class="form-control" 
                id="column" 
                name="column"
        >
                <option value="none">Please select column..</option>
            {% for column in columns %}
                <option value="{{ column.id }}"
                    {% if column.id= =article.column.id %}
                        selected
                    {% endif %}
                >
                    {{ column }}
                </option>
            {% endfor %}
        </select>
    </div>

    <! -- Text -->.<! -- Submit button -->.</form>.Copy the code

In a slightly different way, the form determines whether column.id is equal to article.column.id, and if so, sets it to the default.

Then modify the view function:

article/views.py

# Update the post.def article_update(request, id):.Determine whether the user submits form data for POST
    if request.method == "POST":...if article_post_form.is_valid():
            ...

            # New code
            if request.POST['column'] != 'none':
                article.column = ArticleColumn.objects.get(id=request.POST['column'])
            else:
                article.column = None.else:...# New and modified code
        columns = ArticleColumn.objects.all()
        context = { 
            'article': article, 
            'article_post_form': article_post_form,
            'columns': columns,
        }

        ...
Copy the code

The code logic is similar. Modify the column function of the article, also completed.

conclusion

This chapter has realized the simple column function, can comfortably classify the article, the Gospel of obsessive-compulsive disorder.

There are also some things that can be improved, such as:

  • Click the Columns button to display all articles in the same column. This function is very similar to the sort of the hottest articles and search articles you’ve learned before. Remember the filter() method?

  • Add, delete, change and check column Model.

    For individual blogs, column data changes are usually minimal. If you don’t want to add, delete, modify, and check, it is perfectly possible to modify data in the background.

I will not repeat the above. It is left to the reader to try to implement.

  • If you have any questions please leave a message on Doucet’s personal website and I will reply as soon as possible.
  • Or Email me a private message: [email protected]
  • Project code: Django_blog_tutorial