I'm trying to add a category section to my blog post form using django, the category field is created and I haven't got any error but the dropdown is not created.
models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class Category(models.Model):
name = models.CharField(max_length=200)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('posts')
class Post(models.Model):
STATUS = [
(0, 'Drafted'),
(1, 'Published'),
]
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
published_on = models.DateTimeField(auto_now=True)
content = models.TextField()
status = models.IntegerField(choices=STATUS, default=0)
category = models.CharField(max_length=200, default='uncategorized')
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('my_blog:posts')
forms.py
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'author', 'category', 'content')
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'author': forms.Select(attrs={'class': 'form-control'}),
'category': forms.Select(attrs={'class': 'form-control'}),
'content': forms.Textarea(attrs={'class': 'form-control'}),
}
admin.py
from django.contrib import admin
from .models import Post, Category, Comment
admin.site.register(Post)
admin.site.register(Category)
This method was based on a tutorial and I'm wondering if this is the right way to create category fields. Any help, please?
CodePudding user response:
You should use Category model as ForeignKey in Post model:
class Post(models.Model):
...
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
...
If you have uncategorized posts, you can set them to null. Otherwise, you should use models.CASCADE or models.PROTECT instead of models.SET_NULL at on_delete.
class Post(models.Model):
...
category = models.ForeignKey(Category, on_delete=models.CASCADE)
...
After making changes to your model, you should not forget the following commands:
python manage.py makemigrations
python manage.py migrate
CodePudding user response:
you should give a unique=True
to your Category
name and in your Post
model for category use a ForeignKey
instead of CharField
. By default a ForeignKey
will be a select field so you shouldn't need to do much else.
Like this :
class Category(models.Model):
name = models.CharField(max_length=200, unique=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('posts')
class Post(models.Model):
STATUS = [
(0, 'Drafted'),
(1, 'Published'),
]
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
published_on = models.DateTimeField(auto_now=True)
content = models.TextField()
status = models.IntegerField(choices=STATUS, default=0)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='posts')
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('my_blog:posts')