this question might get a bit large,i will try to explain perrty much everything whats going on.below is my heading model which fills the slug field itself by whatever is the title:
class Heading(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=5000)
content =RichTextUploadingField ()
image= models.ImageField(null=True,blank=True)
date = models.DateField(default=datetime.now())
time = models.TimeField(default=datetime.now())
slug = models.SlugField(unique=True, null=True, blank=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Heading, self).save(*args, **kwargs)
my title is in a foreign language(nepali language to be specific)
below is the image of my admin panel to fill up the heading class
as you can see my title is in foreign language but my slug field is filled automatically by converting that title in english language which is not what i want,i want my slug field to be filled in the same language as my title field.i did some search and a module called unidecode might be the solution to it,i tried using it too but since its documentation is not well i couldn't get hook of it.so if there is any other solution or how to make proper use of unidecode?any kind of help or clue would be greatly appreciated
The problem is, slugification happens in JavaScript (at least in the standard Django admin), before it reaches the server (you can look up urlify.js in the admin contrib package).
There's a new option on SlugField called allow_unicode, which might do what you want, but it's been introduced in Django 1.9.
If you cannot upgrade to 1.9 yet, you could in theory set up some endpoint on your server that would take a string, run unidecode on it, and return it, and then cook up some custom JavaScript code that would override the default slugification in the admin, but that sounds like quite a lot of work.
Another option would be to hide the slug field from the admin altogether, and do something similar to that snippet of code you posted in your question, except you should probably do this in the ModelAdmin class instead of the model itself (and you probably want to use unidecode there before passing the string to slugify).
Firstly you have to import "SLUGIFY" [from django.utils.text import slugify].
Secondly, In model,
slug = models.SlugField(allow_unicode=True, unique=True, null=True,
blank=True)
After that:
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
if not self.slug:
slug_str = f"{self.title}"
self.slug = slugify(slug_str, allow_unicode=True)
super(Blog, self).save(*args, **kwargs)
Finally Don't forget to add
[ALLOW_UNICODE_SLUGS = True]
in settings.py.
Related
I've encountered a problem with Django's built-in slugify function. I'm building a website using Django framework. The site must have a forum app. After a bit of searching, I've found one. It works great, however, it's using the slugify function heavily on the topic titles to create "human readable" links to its pages. The problem is, we are writing in Russian, so as the result, it generates non-ASCII URLs which look like an unreadable mess of unicode data when trying to copy the link from the browser (and also throws an exception when trying to log them).
Is there a way to override the Django's django.utils.text.slugify globally for the whole project so I don't need to include half of the third party library only to change the import statements in their models.py ?
One way where it is not global is to write your own slugify function and then you can utilise that by calling it in overridden save method of the model where you want to slugify the title/name field.
Eg.
class Post(models.Model):
title = models.CharField(max_length=512)
slug = models.CharField(max_length=1024)
def save(self, *args, **kwargs):
your_slugify_function(self, self.title)
super(Post, self).save(*args, **kwargs)
I think you can define a abstract model class with overriding the save method with slugify function. Like this:
class AbstractBase(models.Model):
slug = models.SlugField()
class Meta:
abstract = True
def save(self, *args, **kwargs):
self.slug = slugify.Slugify(self.slug)
return super(AbstractBase, self).save(*args, **kwargs)
And sub-class your rest of the models from this abstract class like:
class Post(AbstractBase):
# rest of the post fields
In this way, slugify will be done only in one place and work globally across all models.
I'm a beginner with Django, and first time askig :)
I'm following a simple tutorial on generating a slug for a string (let's say a slug for a blog post generated from its title).
Perhaps I'm following an outdated guide, perhaps I'm missing a basic thing, I have no idea.
Django 2.0
Python 3.6
I am trying to do a very simple task of slugifying a simple string, so:
User enters a string in a simple form
When hitting 'save', the title goes through slugify and creates the
slug
Save.
models.py
from django.db import models
class Testmodel(models.Model):
title = models.CharField(max_length=220)
slug = models.SlugField(unique=True, null=True)
def __str__(self):
return self.title
views.py
from django.views.generic.edit import CreateView
class TestCreate(CreateView):
model = Testmodel
fields = '__all__'
forms.py
from django.forms import ModelForm
from .models import Testmodel
class TestCreateForm(ModelForm):
class Meta:
model = Testmodel
fields = '__all__'
Up until here everythig works, if I enter the slug manualy. In order to do it automaticaly, I have tried:
Overriding the save() method withing my ModelForm class.
Overriding the form_valid() method within the CreateView
Overriding the save() method within the model itself.
Tried to connect a pre_save signal to the model.
In all of these 4 tries, I had the same results:
When generating the form with the slug field, I couldn't do anything because it was required.
When generating the form without the slug field, nothing happens when I hit save.
The only way I have found to dodge this issue is to set the slug field to blank = True as well. I am not sure how secure it is, though?
Thank you!
Welcome to StackOverflow. You've written a wonderfuly constructed question (Cheers!)
When generating the form with the slug field, I couldn't do anything because it was required.
Okay so first we exlcude the slug because we want it to be autogenerated.
You can do this by
class TestCreateForm(ModelForm):
class Meta:
model = Testmodel
exclude = ['slug']
Now you'll get a form without the slug field.
When generating the form without the slug field, nothing happens when I hit save.
Now we override the save() function of the model itself since slug is a part of the model.
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)
But this will generate the slug everytime the model is saved.
We can go a step further and make sure the slug is set only if the model is 'created' and not every time it is 'updated'
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
I'm using django-favorites from https://bitbucket.org/last_partizan/django-favorites/overview, and I set everything right and when I run the code it gave me 'FavoriteManager' object has no attribute 'get_query_set'. The error was occuring from the django-favorites models.py from this line
qs = self.get_query_set().filter(content_type=content_type, object_id=obj.pk)
So I thought, I need to specify object. So I'm trying to use fav button for all my Post, so I need to change obj to Post. But even after changing I get same error. What is going on with this?
This is models.py inside favorite app, where error is occurring
def favorites_for_object(self, obj, user=None):
""" Returns Favorites for a specific object """
content_type = ContentType.objects.get_for_model(type(obj))
qs = self.get_query_set().filter(content_type=content_type,
object_id=obj.pk)
if user:
qs = qs.filter(user=user)
return qs
This is where I'm calling fav_item
<div class="actions">{% fav_item post user %}</div>
Lets say I want to put fav_item on my category model
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
slug = models.CharField(max_length=100, unique=True)
author = models.OneToOneField(settings.AUTH_USER_MODEL, unique=True)
def save(self, *args, **kwargs):
self.slug = uuslug(self.name,instance=self, max_length=100)
super(Category, self).save(*args, **kwargs)
def __unicode__(self):
return self.name
Then doesn't it make sense to import
main.models import Category
and switch obj to Category. Unfortunately there's not much documentation here: https://bitbucket.org/last_partizan/django-favorites/overview
This problem is related to Django version. The method get_query_set has been removed from Django 1.8.x . Before that, this method was used by RenameManagerMethods. Check this github source: https://github.com/django/django/blob/stable/1.7.x/django/db/models/manager.py#L56
Also django-favorites was last updated in 2013, as I can see from the source. You should consider downgrading your Django version.
I am using Python 2.7 and Django 1.6.3
I want to define extra model field which is not actually in db table. I have a way which is defining a callable method with property annotation like;
class MyClass(models.Model):
my_field = models.CharField(max_length=50)
#property
def my_extra_field(self):
return self.my_field+'extra value'
This works fine to show it on admin change list pages. But the extra field is not on db level. It is being generated on programming level. Django asks it for every model object.
This cause me some troubles. My all admin change list pages have capability of exporting as excel or some other type. I am using admin query set to build that report. I have also jasper reports mechanism that works with SQL select queries. So, I, want to use the queryset to take this select query.
I think being able to define extra fields on db level is important for something. Not just for reason of mine. So, the question all about this.
Is there a way to define an extra custom fields on db level instead of programming level in Django.
Thank you!.
Edited
Adding it to admin list_filter is also another problem if it is not really a field. Django does not allow you to add it.
Could you create a new database field and then overwrite the save method to populate that field? I do that often to create a marked up version of a text field. For example:
class Dummmy(models.Model):
content = models.TextField()
content_html = models.TextField(editable=False, null=True)
def save(self, *args, **kwargs):
self.content_html = markdown(self.content)
super(Dummmy, self).save(*args, **kwargs)
So for you:
class MyClass(models.Model):
my_field = models.CharField(max_length=50)
my_extra_field = models.CharField(editable=False, null=True)
def save(self, *args, **kwargs):
self.my_extra_field = self.my_field + 'extra value'
super(MyClass, self).save(*args, **kwargs)
I'm trying to find a good tutorial for django how to create multiple tags in a model.
For example:
class Tag(models.Model):
name = models.CharField()
class Sample(models.Model):
name = models.CharField()
urlA = models.CharField()
urlB = models.CharField()
tagA = models.ManyToManyField(Tag)
tagB = models.ManyToManyField(Tag)
I would like to display the tags as an input field and separate by ',' and split in the save method. So I'd like to see 2 different input for the 2 tag field.
If you have an easy way to do or know a good tutorial, please tell me! :)
Thank you guys!
Edit: you do not have to have the actual table sets over laid. You can generate any queryset you want to inn your views. Your url conf can be set up to display the detail view from multiple url. If i am still not understanding then please refine your question.
For having multiple anything tags categories your either going m21 or m2m. So when you create your tags you can add them one by one. Are you familiar with what the Django ORM has to offer with some of its admin functionality? Please give the documentation a good look through. Your approach to this problem is anything but reasonable. Not trying to rub you the wrong way I'm no genius. You would do something like so.
class Tag(models.Model):
title = models.CharField(max_length=250, blank=True)
slug = models.SlugField(blank=True
class Meta:
verbose_name = "tag"
verbose_name_plural = "tags"
ordering = ['title']
#models.permalink
def get_absolute_url(self):
return "/tags/%s/" % self.slug
class Entry(models.Model):
title = models.CharField(max_length=250, blank=True)
body = models.TextField()
tags = models.ManyToMany('Tag')
slug = models.SlugField()
#models.permalink
def get_absolute_url(self):
return "/blog/%s/" % self.slug
There's a little more code to be done for the EntryAdmin and the TagAdmin models, Many other things that can be done as well. I am not sure what you are trying to achieve with that if you could be more clear? Thank you, the above is a rough illustration of how I would approach it.
I found a solution from here:
https://dev.to/thepylot/how-to-add-tags-to-your-models-in-django-django-packages-series-1-3704
django-taggit is very useful for tagging.
It is
a reusable application that primarily offers you a Tag model, and a manager for easily adding tags to any model.
pip install django-taggit
After that, open settings.py and edit the installed apps section:
INSTALLED_APPS = [
...
'taggit'
]
After that, edit your model and add tags like this:
tags = TaggableManager()
The TaggableManager will show up automatically as a field in a ModelForm or in the admin.
Documentation: https://django-taggit.readthedocs.io/en/latest/index.html