Group by in manytomany fields in Django - django

Ive got a simple task. There are two models
class Song(models.Model):
song_title = models.CharField(max_length=200)
song_genres = models.ManyToManyField(Genres, null=True, related_name='genres')
...
class Genre(models.Model):
genre_title = models.CharField(max_length=50)
genre_uri = models.SlugField(max_length=100, unique=True, blank=True)
...
I need to get list of most popular tags with song's count. For example:
[{<Genres: Pop>, 20}, {<Genres: Rap>, 15} ...]
For foreign key i can use
Song.objects.annotate(count=Count('song_genres')).order_by('-count')[:5]
but it doesn't work with manytomany fields. Any help would be much appreciated.

Assuming related_name on song model is 'songs', because it should be.
Genres.objects.annotate(songs_count=Count('songs')).order_by('-songs_count')[:10].values('id', 'songs_count')
This will give you id of all top 10 generes and songs_count in them.

Related

Django add a field to a model based on another model

I have a model for a product:
class Product(models.Model):
name = models.CharField(verbose_name=_("Name"), max_length=120)
slug = AutoSlugField(populate_from="name", verbose_name=_("Slug"), always_update=False, unique=True)
I want to have a separate model ProductFields:
class ProductFields(models.Model):
field_name = models.CharField()
field_type = models.CharField()
field_verbose_name = models.CharField()
field_max_length = models.IntegerField()
filed_null = models.CharField()
field_blank = models.BooleanField()
field_default = models.CharField()
...
So the idea is whenever I add new ProductField I want Product model to migrate that added field to its database.
For Example:
ProductFields.objects.create(field_name='description', field_type='CharField', field_verbose_name='Description', field_max_length=255, filed_null=True, filed_blank=True)
This should transform Product modal to:
class Product(models.Model):
name = models.CharField(verbose_name=_("Name"), max_length=120)
slug = AutoSlugField(populate_from="name", verbose_name=_("Slug"), always_update=False, unique=True)
description = models.CharField(verbose_name="Description", max_length= 255, null=True, blank=True)
Please let me know if you have any idea how this can be done?
If you're looking for a way to create a dynamic model you can look into these suggestions.
HStoreField using django-hstore : https://django-hstore.readthedocs.io/en/latest/
JSONField: JSONField is similar to HStoreField, and may perform better with large dictionaries. It also supports types other than strings, such as integers, booleans and nested dictionaries.https://django-pgfields.readthedocs.io/en/latest/fields.html#json-field
Or you can use a NoSQL database (Django MangoDB or another adaptation)

Django model order the queryset based on booleanfield True/False that related with User FK profile

I have two django models as follows:
The first one is a user profile, which has a FK to User model:
class Profile(models.Model):
PRF_user = models.OneToOneField(User, related_name='related_PRF_user', on_delete=models.CASCADE)
PRF_Priority_Support = models.BooleanField(default=False)
and the second is ticket model which has a FK to User model:
class ticket(models.Model):
ticket_status_options = [
('open', 'open'),
('wait_customer_reply', 'wait_customer_reply'),
('replied_by_staff', 'replied_by_staff'),
('replied_by_customer', 'replied_by_customer'),
('solved', 'solved'),
]
TKT_USER = models.ForeignKey(User, related_name='TKT_USER', on_delete=models.CASCADE)
TKT_DEB = models.ForeignKey('Site_departments', related_name='related_ticket_department', on_delete=models.CASCADE)
TKT_SUB = models.CharField(max_length=50, db_index=True, verbose_name="ticket subject")
TKT_BOD = models.TextField(verbose_name="ticket body")
TKT_image_attachment = models.ImageField(upload_to='TKT_img_attachment', blank=True, null=True , default=None)
TKT_CREATED_DATE = models.DateTimeField(auto_now_add=True)
TKT_UPDATED_DATE = models.DateTimeField(auto_now=True)
I want to sort the tickets based on user profile Priority_Support:
If the user profile PRF_Priority_Support is True, I want to sort it first inside my views QuerySet, otherwise (if PRF_Priority_Support is False) I want to sort it normally.
How can I do this?
You should name your model starting with a capital letter.
And for ordering the tickets, you can use something like this:
' queryset_list = ticket.objects.order_by('-TKT_USER__related_PRF_user__PRF_Priority_Support')
In filtering, when you want to span relationships, you use double underscore __ .
More on this here:
https://docs.djangoproject.com/en/3.1/topics/db/queries/#lookups-that-span-relationships
Another way is adding ordering to your model's Meta class.
For Example:
MyModel(models.Model):
class Meta:
ordering = ('-my_boolean_field ',)
Hi you should filter as follow:
Model.objects.filter(field=True) or False depending on what you need
Regards

Stop Django from autofilling manytomany fields in admin

I have the following models:
class Color(models.Model):
name = models.CharField(max_length=50, null=False, blank=False)
def __str__(self):
return self.name
class Flower(models.Model):
flower_number = models.PositiveSmallIntegerField(
default=1,blank=True, null=True)
petal_color = models.ManyToManyField(Color,blank=True, related_name="%(app_label)s_%(class)s_petal",
related_query_name="%(app_label)s_%(class)s")
petal_outer_color = models.ManyToManyField(Color,blank=True, related_name="%(app_label)s_%(class)s_petal_outer",
related_query_name="%(app_label)s_%(class)s")
class Meta:
abstract = True
class Plant(Flower):
name = models.CharField(max_length=50, null=False, blank=False, unique=True)
On the Admin I just have:
admin.site.register(Plant)
When I go into the Django admin and fill out either of the manytomany petal_color or petal_outer_color with data the other manytomany field automatically gets filled when it saves. How do I stop this from happening? Nothing shows up as an error and I tried going back and deleting and re-entering data but it still happens
Try using symmetrical=False in the ManyToManyField, that might be causing the issue here as you have two M2M fields going to the same model.
Read up on symmetrical in the Django docs.
Do something like this
class Flower(models.Model):
flower_number = models.PositiveSmallIntegerField(
default=1,blank=True, null=True)
petal_color = models.ManyToManyField(Color,blank=True, symmetrical=False related_name="%(app_label)s_%(class)s_petal",
related_query_name="%(app_label)s_%(class)s")
petal_outer_color = models.ManyToManyField(Color,blank=True, symmetrical=False, related_name="%(app_label)s_%(class)s_petal_outer",
related_query_name="%(app_label)s_%(class)s")
class Meta:
abstract = True
By default, the value of symmetrical is True for Many to Many Field which is a bi-directional relationship.
The ManyToManyField is assumed to be symmetrical – that is, if I am your friend, then you are my friend.

Multiple ForeignKeys in Through model for Many-to-many relation to same model

I've got a many-to-many relation from a model called Resource to itself through an intermediary model called RelatedResource:
class Resource(TimeStampedModel):
title = models.CharField(max_length=100, unique=True) # book title, person's name, video title, etc.
description = models.TextField(max_length=500, null=True, blank=True)
link = models.URLField(max_length=500, blank=True, null=True) # dynamically generated for youtube and amazon; todo: uniqueness
resourceID = models.CharField(max_length=20, blank=True, null=True) # todo: uniqueness
picture = models.URLField(max_length=500, blank=True)
tags = TaggableManager()
...
class RelatedResource(models.Model):
input = models.ForeignKey(Resource, related_name="input_resource")
output = models.ForeignKey(Resource, related_name="output_resource")
input_affiliate = models.ForeignKey(Resource, related_name="while_with", blank=True, null=True)
reason = models.CharField(max_length=500)
...
Django complains that having more than 2 foreign keys to Resource is ambiguous, of course, because then it doesn't know which two of the three ForeignKey fields apply in the many-to-many relation.
Is there any way I can keep all 3 ForeignKey fields in the intermediary model and tell Django which 2 are meant for the many-to-many relation?
I think what you are trying to do is recursive relationship.
It is described in here.
https://docs.djangoproject.com/en/1.6/ref/models/fields/#recursive-relationships
And here.
Django recursive relationship

Ordering a Foreign Key Field by Date Added

I have the following two models:
class Position(models.Model):
position = models.CharField(max_length=100)
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
positions = models.ManyToManyField(Position, blank=True, null=True)
This creates a database table called userprofile_userprofile_positions, with the following three columns:
id
userprofile_id
position_id
How would I add a fourth field to this table --
created_at = models.DateTimeField(auto_now_add=True)
I would like to do this through django, if possible. Thank you.
Create a new model and specify it in the through attribute of your ManyToMany. The Django docs have a section on this exact use case: Extra fields on many-to-many relationships.