автоматическое заполнение поля слагов не работает в Django - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь создавать посты, в которых в качестве URL-адреса используется слаг.Я добавляю поле слага, но оно не заполняется автоматически.Я хочу, чтобы это автоматически заполнялось.Пока я сделал это.Я добавляю pre_save в конце.

Я пытался сохранить сообщения от администратора django, он говорит что-то вроде этого

Это поле обязательно для заполнения.

сообщений / моделей.py

from django.db import models
from django.core.validators import FileExtensionValidator
from django.db.models.signals import pre_save
from django.utils.text import slugify
# Create your models here.



class Category(models.Model):
    title = models.CharField(max_length = 120, verbose_name="Title" )
    updated_at = models.DateTimeField(auto_now_add=True, verbose_name="Updated at")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created at")
    class Meta:
        verbose_name = "Category"
        verbose_name_plural = "Categories"
        ordering = ['title']
    def __str__(self):
        return self.title



class Posts(models.Model):
    title = models.CharField(max_length=60)
    slug = models.SlugField(unique = True)
    file_upload = models.FileField(null= True, blank=True, validators=[FileExtensionValidator(['pdf'])])
    content = models.TextField()
    category = models.ForeignKey(Category, null= True,verbose_name="Category", on_delete=models.CASCADE)
    updated = models.DateTimeField(auto_now=True, auto_now_add=False)
    timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)

    # class Meta:
    #     verbose_name = "Post"
    #     verbose_name_plural = "Posts"
    #     ordering = ['-created_at']


    def __unicode__(self):
        return self.title 

    def __str__(self):
        return self.title

def create_slug(instance, new_slug=None):
    slug = slugify(instance.title, allow_unicode = True)
    if new_slug is not None:
        slug = new_slug
    qs = Posts.objects.filter(slug=slug).order_by("-id")
    exists = qs.exists()
    if exists:
        new_slug = "%s-%s"%(slug, qs.first().id)
        return create_slug(instance, new_slug=new_slug)
    return slug

def pre_save_post_receiver( instance, sender,*args, **kwargs):
    if not instance.slug:
        instance.slug = create_slug(instance)
pre_save.connect(pre_save_post_receiver, sender=Posts)

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Вы можете использовать django-slugger

, а затем добавить это к администратору добавить

admin.py

prepopulated_fields = {'slug': ('title',), }
0 голосов
/ 19 февраля 2019

Начиная с вашего кода instance.title всегда важно для генерации значения слага.Тогда одним из возможных способов без запуска сигнала pre_save является перезапись функции сохранения модели и присвоение ей значения.

def create_slug(title, new_slug=None):
    slug = slugify(title, allow_unicode = True)
    if new_slug is not None:
        slug = new_slug
    qs = Posts.objects.filter(slug=slug).order_by("-id")
    exists = qs.exists()
    if exists:
        new_slug = "%s-%s"%(slug, qs.first().id)
        return create_slug(title, new_slug=new_slug)
    return slug



class Posts(models.Model):
    title = models.CharField(max_length=60)
    slug = models.SlugField(unique = True)
    file_upload = models.FileField(null= True, blank=True, validators=[FileExtensionValidator(['pdf'])])
    content = models.TextField()
    category = models.ForeignKey(Category, null= True,verbose_name="Category", on_delete=models.CASCADE)
    updated = models.DateTimeField(auto_now=True, auto_now_add=False)
    timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)

    # class Meta:
    #     verbose_name = "Post"
    #     verbose_name_plural = "Posts"
    #     ordering = ['-created_at']

    def save(self, *args, **kwargs):
        if not self.slug:
               self.slug = create_slug(self.title)
        return super(Posts, self).save(*args, **kwargs)  # important to call this

    def __unicode__(self):
        return self.title 

    def __str__(self):
        return self.title

Я действительно надеюсь, что это решение будет работать.Другой возможный способ использовать вызываемую по умолчанию функцию поля link , но из вашего кода я вижу, что title также важно.Я не совсем уверен, но следующая вещь также может работать.

def create_slug(title, new_slug=None):
        slug = slugify(title, allow_unicode = True)
        if new_slug is not None:
            slug = new_slug
        qs = Posts.objects.filter(slug=slug).order_by("-id")
        exists = qs.exists()
        if exists:
            new_slug = "%s-%s"%(slug, qs.first().id)
            return create_slug(title, new_slug=new_slug)
        return slug



class Posts(models.Model):
    title = models.CharField(max_length=60)
    slug = models.SlugField(unique = True, default=create_slug(self.title))
    file_upload = models.FileField(null= True, blank=True, validators=[FileExtensionValidator(['pdf'])])
    content = models.TextField()
    category = models.ForeignKey(Category, null= True,verbose_name="Category", on_delete=models.CASCADE)
    updated = models.DateTimeField(auto_now=True, auto_now_add=False)
    timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)

    # class Meta:
    #     verbose_name = "Post"
    #     verbose_name_plural = "Posts"
    #     ordering = ['-created_at']



    def __unicode__(self):
        return self.title 

    def __str__(self):
        return self.title
...