Blog with Django (Codemy.com) - 12 ~ 15 Categories/ Slugify Category Page URLs/ Add category navbar links

이다연·2021년 3월 8일
0

Django

목록 보기
7/33
post-thumbnail

Categories

1. Add category model

for scalability, better to make a model.

models.py

class Category(models.Model):
   name = models.CharField(max_length=255)

   def __str__(self):
       return self.name

   def get_absolute_url(self): #url name
       # return reverse('article-detail', args=(str(self.id)))
       return reverse('home')

change in model: makemigrations - migrate

change in admin.py

admin.site.register(Category)

2. Add model into form

Note that field 'category' added as Select

forms.py
'category': forms.Select(attrs={'class': 'form-control'}),

class PostForm(forms.ModelForm): 
    class Meta:
        model = Post
        fields = 
        ('title', 'title_tag', 'author', 'category', 'body')

        widgets = {
			~
            'category': 
            forms.Select(attrs={'class': 'form-control'}),
			~
        }

3. Populate dropdown menu

1. hard coded

forms.py

choice = [('coding', 'coding'), ('sports', 'sports')]

class PostForm(forms.ModelForm): 
    class Meta:
        model = Post
        fields = ('title', 'title_tag', 'author',
        	'category', 'body')

        widgets = {
           ~
            'category': forms.Select(choices=choice, 
            attrs={'class': 'form-control'}),
			~
        }

2. dynamic

'placeholder':choices -> it's like print, to check the value

  • we added category values through admin site.

forms.py

choices = Category.objects.all().values_list('name','name') 
#name is from model field
choice_list = []

for item in choices:
    choice_list.append(item)

class PostForm(forms.ModelForm):
		~
        widgets = {
            'category': forms.Select(choices=choice_list, 
             attrs={'class': 'form-control'}),
        }

4. Create category add page

1. views

views.py

class AddCategoryView(CreateView):
    model = Category
    template_name = 'add_category.html'
    fields = '__all__' 

2. template

create add_category.html

{% extends 'base.html' %}
{% block title %} New Category {% endblock %}

{% block content %}
{% if user.is_authenticated %}
<h1> Add Category </h1>
<br/>

<div class="form-group">
    <form method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <br/>
        <button class="btn btn-secondary"> Category </button>
    </form>
</div>
{% else %}
You are not allowed here. Please log in.

{% endif %}

{% endblock %}

3. urls

urlpatterns = [
   ~
    path('add_category', AddCategoryView.as_view(),
    	  name="add_category"),

  • Add Category button directs to Home. it's possible with def get_absolute_urlat models.py

models.py

class Category(models.Model):
 	~
    def get_absolute_url(self): 
        return reverse('home')

5. Show posts by Category

for a change, make it as a function based view.

  • <str:cats> for categories

1. urls

    path('category/<str:cats>/', CategoryView, name="category"),

2. views

def CategoryView(request, cats):
    category_posts = Post.objects.filter(category=cats)
    return render(request, 'categories.html', 
  		  {'cats':cats, 'category_posts':category_posts})

3. templates

categories.html

{% extends 'base.html' %}

{% block content %}
{% if category_posts %}

    <h1> Categorised by {{cats}} </h1>

    <ul>
    {% for post in category_posts %}
        <li><a href="{% url 'article-detail' post.pk %}">
        {{ post.title }}</a> {{ post.category }} - {{ post.author.first_name }}{{ post.author.last_name }} - {{ post.post_date}}

            {% if user.is_authenticated %}
                <small><a href="{% url 'update_post' post.pk %}"> (Edit)  </a></small>
                <small><a href="{% url 'delete_post' post.pk %}"> (Delete) </a></small>
            {% endif %}
        <br/>{{ post.body|slice:"100"|safe }} </li>

    {% endfor %}
    </ul>
{% else%}
    sorry this page does not exist.

{% endif %}
{% endblock %}

home.html

<a href="{% url 'category' post.category %}">
		{{ post.category }}</a>

  • under sports category
  • under not existing category

Slugify Category page URLs

A Slug used in URLs. A slug field in Django is used to store and generate valid URLs for your dynamically created web pages.

When making url, It should have space in between words; however, when creating category, we might not take it into account. Hence this happenes
Note that there is a whitespace in between coding and tutorial.

Solution:

1. template

pipe slugify removes whitespace
post.category|slugify

<a href="{% url 'category' post.category|slugify %}">
	{{ post.category }}</a>
  • slugify added dash in between words, but this doesn't direct to correct page.

2. view

use python replace() function

def CategoryView(request, cats):
    category_posts = Post.objects.filter(
    	             category=cats.replace('-', ' '))
    return render(request, 'categories.html', 
                  {'cats':cats.replace('-', ' '), 
                  'category_posts':category_posts})

Add Category Navbar

outside authentication. we want to show it regardless authority.

base.html

</button>


    <div class="collapse navbar-collapse" id="navbarSupportedContent">
       <ul class="navbar-nav mr-auto">
        {% if cat_menu %}

        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            Categories
          </a>
          <div class="dropdown-menu" aria-labelledby="navbarDropdown">
            {% for item in cat_menu %}
             <a class="dropdown-item" href="{% url 'category' item|slugify %}">{{ item }}</a>
            {% endfor %}
          </div>
        </li>
        {% endif %}


        {% if user.is_authenticated %}
  • get hold of value with {{ cat.menu }}
    views.py
class HomeView(ListView):
    ~
    #pass context
    def get_context_data(self, *args, **kwargs):
        cat_menu = Category.objects.all()
        context = super(HomeView, self).get_context_data(*args, **kwargs)
        context["cat_menu"] = cat_menu
        return context

Because we made 'get_context_data' function in a HomeView, Categories dropdown menu disapears when we move to other pages. (Even though it was written in base.html)

We have to add def get_context_data(self, *args, **kwargs): under each Views.

profile
Dayeon Lee | Django & Python Web Developer

0개의 댓글