Slugify self.title + random numbers - django

I hope you're well. I've two questions for you:
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
url_image = models.URLField(max_length=200, default='SOME STRING')
author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='blog_posts')
updated_on = models.DateTimeField(auto_now= True)
name_site = models.CharField(max_length=200, default='NA')
url_site = models.URLField(max_length=200, default='https://exemple.fr/')
content = models.TextField()
I. I want my title (unique=False) because I have some similar titles. So is it possible to save my slug (editable=False) with slugify with something like that:
slug_str = "%s %s" % (self.title, 4 random numbers like that 0476)
If anyone has a better idea, I'm interested in
Thanks a lot :) have a good holidays and take care

Here are a couple functions that I use. You pass in the model instance and the desired title into unique_slugify which will continue trying to add random strings until one is created that doesn't already exist.
import random
import string
def random_string_generator(size=10, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
def unique_slugify(instance, slug):
model = instance.__class__
unique_slug = slug
while model.objects.filter(slug=unique_slug).exists():
unique_slug = slug
unique_slug += random_string_generator(size=4)
return unique_slug
I usually use it by overriding the model save method.
class YourModel(models.Model):
slug = models.SlugField(max_length=200, unique=True)
title = models.CharField(max_length=200)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = unique_slugify(self, slugify(self.title))
super().save(*args, **kwargs)

in my opinion, it doesn't make sens two posts may have the same title even with two different slugs, it even confuses readers and even worst it's very bad for SEO. i suggest you to avoid this path and try to review the logic
in models.py
class Post(models.Model):
title = models.CharField(_('title'), max_length=200,
unique=True, # title should be unique
help_text=_('The title of the entry.')
)
slug = models.SlugField(_('slug'), max_length=200,
unique=True, null=True, blank=True,
help_text=_(
'If blank, the slug will be generated automatically '
'from the given title.'
)
)
[..]
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title) # here you don't need to add random numbers since the title is already unque
super().save(*args, **kwargs)
in admin.py
class PostAdmin(admin.ModelAdmin):
list_display = ('title', .. )
readonly_fields = ('slug', .. ) # Add slug to read_only fields to make it not editable if you want

Related

count the number of posts

I have created a website and want to count user generated posts.
I tried to do it as follows:
models.py
class Blog(models.Model):
user = models.ForeignKey(
User,
related_name='user_blogs',
on_delete=models.CASCADE
)
category = models.ForeignKey(
Category,
related_name='category_blogs',
on_delete=models.CASCADE
)
title = models.CharField(
max_length=250
)
slug = models.SlugField(null=True, blank=True)
banner = models.ImageField(upload_to='blog_banners')
description = RichTextField()
created_date = models.DateField(auto_now_add=True)
def __str__(self) -> str:
return self.title
def save(self, *args, **kwargs):
updating = self.pk is not None
if updating:
self.slug = generate_unique_slug(self, self.title, update=True)
super().save(*args, **kwargs)
else:
self.slug = generate_unique_slug(self, self.title)
super().save(*args, **kwargs)
templates
<span>Posts: <strong>{{account.user_blogs.count}}</strong></span>
but it doesn't work
what is the problem? should I rewrite the code at all?
If you're trying to count posts created by the logged-in user
<span>Posts: <strong>{{ request.user.user_blogs.count }}</strong></span>

How to create slug of many to many fields in django?

I want to make slugs on post save for my model using three fields one charfield and two ManytoMany Fields but getting error during saving.
Here is my code:
Heading ##class product(models.Model):
id = models.AutoField(primary_key=True)
image = models.ForeignKey(all_images, verbose_name='Product Images', on_delete=models.CASCADE, related_name='proimages')
ProductName = models.CharField(max_length=200, null=False,default="None", blank=False,verbose_name="Product Name")
CategoryName = models.ManyToManyField(category,related_name='procat', blank=False,verbose_name="Category Name")
SubcatName = models.ManyToManyField(subcategory,related_name='prosubcat', blank=False,verbose_name="Sub-category Name")
description = RichTextUploadingField(blank= False,verbose_name="Description")
price = models.IntegerField(default=100, null=True, blank=True, verbose_name='Price')
slug = models.SlugField(max_length=55, blank=True, null=True)
def get_slug(self):
slug = self.ProductName
try:
for items in self.SubcatName.all():
slug +=items.name
try:
for items in self.CategoryName.all():
slug +=items.CategoryName
except:
pass
except:
pass
return slugify(slug)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = self.get_slug()
super(product, self).save(*args, **kwargs)

How to display two not associated models on one page via admin interface?

I have two models, not connected by ForeignKey. I would to display them on one page in admin interface, in the way like inlines in Django.
I can't associate PostFile with Post, because uploaded medias should be available to every Post which was and will be created in future. I have no idea what I can do if inlines are unavailable.
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published')
)
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique_for_date='publish_date', blank=True)
author = models.ForeignKey(User, related_name='blog_posts', on_delete=models.CASCADE, blank=True)
content = MarkdownxField()
publish_date = models.DateTimeField(default=timezone.now)
creation_date = models.DateTimeField(auto_now_add=True)
last_update_date = models.DateField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
tags = models.ManyToManyField(Tag)
objects = models.Manager()
class Meta:
ordering = [
'-publish_date'
]
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('blog:post_detail',
args=[
self.publish_date.strftime('%Y'),
self.publish_date.strftime('%m'),
self.publish_date.strftime('%d'),
self.slug
])
#https://github.com/neutronX/django-markdownx/issues/83
def formatted_markdown(self):
return markdownify(self.content)
class PostFile(models.Model):
file_name = models.CharField(max_length=200, blank=True)
file_object = models.FileField(upload_to='post_files/')
file_upload_date = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
if not self.file_name:
self.file_name = self.file_object.name
super(PostFile, self).save(*args, **kwargs)
def file_url(self):
return self.file_object.url
def __str__(self):
return self.file_name
I would to receive in output a Post model admin page, where on the bottom I have listed all PostFile objects. This will give me easy and fast acces to PostFile-object url on media folder. I don't want each time to open new tab, and to go to PostFile model admin page to check url of object.

How to change slug if same string is stored in it?

I am working with slug on my model. Although, the entries for slug are not unique. When I try to go to a url containing slug, it says get() returned more than one object and I understand that it is because the entries are not unique. How am I supposed to change the slug a bit, if identical entries occur?
model
class Cabin(models.Model):
centre_name = models.ForeignKey(Centre, on_delete=models.CASCADE )
code = models.CharField(max_length=8, unique=True, default=unique_rand)
total_seats = models.IntegerField(blank='False')
category=models.CharField(max_length=100, default=False)
booked_date=models.DateField(blank='False')
released_date=models.DateField(blank='False')
price=models.IntegerField(blank=False, default=None)
slug = models.SlugField(unique=False,default=None,blank=True)
objects = UserManager()
def save(self, *args, **kwargs):
self.slug = slugify(self.category)
super(Client, self).save(*args, **kwargs)
First of all it might be better to set unique=True, such that this can never happen, furthermore you can :
class Cabin(models.Model):
centre_name = models.ForeignKey(Centre, on_delete=models.CASCADE )
code = models.CharField(max_length=8, unique=True, default=unique_rand)
total_seats = models.IntegerField(blank='False')
category=models.CharField(max_length=100, default=False)
booked_date=models.DateField(blank='False')
released_date=models.DateField(blank='False')
price=models.IntegerField(blank=False, default=None)
slug = models.SlugField(unique=True,default=None,blank=True)
objects = UserManager()
def save(self, *args, **kwargs):
slug = originalslug = slugify(self.category)
i = 0
while Cabin.objects.exist(slug=slug):
slug = '{}{}'.format(originalslug, i)
i += 1
self.slug = slug
super(Client, self).save(*args, **kwargs)
We here thus increment i until we found a slug that is not yet used.
Note that there exists an AutoSlugField in the django-extensions package [PyPi], that automates this slug procedure. For example:
from django.db import models
from django_extensions.db.fields import AutoSlugField
class Cabin(models.Model):
centre_name = models.ForeignKey(Centre, on_delete=models.CASCADE )
code = models.CharField(max_length=8, unique=True, default=unique_rand)
total_seats = models.IntegerField(blank='False')
category=models.CharField(max_length=100, default=False)
booked_date=models.DateField(blank='False')
released_date=models.DateField(blank='False')
price=models.IntegerField(blank=False, default=None)
slug = AutoSlugField(populate_from='category')
objects = UserManager()

Django SlugField "This field is required" error

In my django project there's a Blog model which I'm willing to create a slug for it's title:
class Blog(models.Model):
title = models.CharField(default='', max_length=100, verbose_name=u'عنوان')
slug = models.SlugField(max_length=100, allow_unicode=True)
# other stuffs
def save(self, *args, **kwargs):
self.slug = slugify(self.title, allow_unicode=True)
super(Blog, self).save(*args, **kwargs)
def __str__(self):
return self.slug
In django admin I don't fill slug field and when I hit the save button it says:
This field is required.
Isn't my code suppose to create slug automatically? Is there something else I should do?
You should set blank=True for your slug field. This way it won't be required and it will be set to slugified title when save method will run.
class Blog(models.Model):
title = models.CharField(default='', max_length=100, verbose_name=u'عنوان')
slug = models.SlugField(max_length=100, allow_unicode=True, blank=True)