django, many to many relation get_field name - django

I had two django models connected with many to many relationship.
First model:
class Category(models.Model):
name = models.CharField(max_length=255)
products = models.ManyToManyField(Product, related_name='categories',
blank=True, null=True,
verbose_name=_('Products'),
)
second model:
class Product(models.Model):
description = models.TextField(verbose_name=_('Description'), default='')
manifactor = models.CharField(verbose_name=_('Manifactor'), default='Blackberry', max_length=255)
ok, so:
product = Product.objects.all()[0]
product.categories - give me a list of categories for this product.
but:
product._meta.many_to_many - return empty list [].
and product._meta.get_field('categories') - return None.
Why ?
How can I get the verbose name of category field from product object ?

You can add
categories = models.ManyToManyField(Category,
through=Category.products.through)
to your Product model

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)

Getting a column instead of an object when relating with PrimaryKeyRelatedField in Django-Rest-Framework

I have a model for applications, which among many attributes have a category. This category is in fact a key to another model that has the category ID, its name, and so on.
class Application(models.Model):
title = models.CharField(max_length=50)
vendor = models.CharField(max_length=50, default="Unknown", null=False)
.
.
.
category = models.ForeignKey('ApplicationCategory', related_name='applications', null=False, default=1, on_delete=models.SET_DEFAULT)
class ApplicationCategory(models.Model):
name = models.CharField(max_length=20, null=False)
description = models.CharField(max_length=200, null=False)
Then, on the Django REST serializers side I have the serializer for the applications:
class SoftwareSerializer(serializers.ModelSerializer):
category = serializers.PrimaryKeyRelatedField(queryset=ApplicationCategory.objects.all())
class Meta:
model = Application
fields = ['id', 'title', ... 'category']
Which is generating the expected API view, with a dropdown for the categories, but showing them as the ApplicationCategory objects and not giving me their name.
API showing Category dropdown with objects instead of names
Is there a way to access attributes of those objects to show the name in the dropdown, for usability sake?
I have also tried creating a CategorySerializer object (class CategorySerializer(serializers.ModelSerializer)) and then using it as category = CategorySerializer(many=False) but instead of dropdowns, I get open text fields for the attributes of the category.
Am I trying to do something that is not expected to work?
try to define the desired text in str method for your ApplicationCategory class:
class ApplicationCategory(models.Model):
name = models.CharField(max_length=20, null=False)
description = models.CharField(max_length=200, null=False)
#example
def __str__(self):
return '%s: %s' % (self.name , self.description)

How do I create this queryset?

I have the following three models:
class Category(models.Model):
name = models.CharField(max_length=120)
class Experiment(models.Model):
name = models.CharField(max_length=50, unique=True)
categories = models.ManyToManyField(Category)
class Ad(models.Model):
experiment = models.ForeignKey(Experiment, related_name='ads', on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.PROTECT, blank=True, null=True)
I want to create a queryset which returns all ads where ad.category is in ad.experiment.categories.
Some example data to talk through:
Category: ['Cat1', 'Cat2', 'Cat3', Cat4', 'Cat5']
Experiment: [['Exp1',['Cat2','Cat3]],['Exp2',['Cat5','Cat1']]]
Ad: [['Exp1','Cat4'],['Exp1','Cat2']]
The queryset I'm hoping to create would only return the second ad because the ad's category is in the ad's experiment's category.
Any help would be appreciated!
You need to traverse the reverse relationship for experiment and then use an F object to access the ad's category field in the query. The distinct is used because the experiment will have many categories so one ad may have multiple matches on the comparison.
from django.db.models import F
Ad.objects.filter(experiment__category=F('category')).distinct()

Django - How to filter using a ManyToManyField field?

Models:
class Product(models.Model):
...
options = models.ManyToManyField(Option, blank=True)
class Option(models.Model):
...
class ProductVariant(models.Model):
...
product = models.ForeignKey(Product, on_delete=models.CASCADE) # parent product
option = models.ForeignKey(Option, on_delete=models.DO_NOTHING, null=True)
I need to find all the ProductVariants where the option doesn't belong to any options on the parent product Product.
I tried doing the following filtering:
ProductVariant.objects.exclude(option_id__in=[o.pk for o in F('product__options')])
But I got the following exception:
'F' object is not iterable
Try filtering by Count instead:
ProductVariant.objects.annotate(product_count=Count('option__product')).filter(product_count=0)

django queryset for many-to-many field

I have the following Django 1.2 models:
class Category(models.Model):
name = models.CharField(max_length=255)
class Article(models.Model):
title = models.CharField(max_length=10, unique=True)
categories = models.ManyToManyField(Category)
class Preference(models.Model):
title = models.CharField(max_length=10, unique=True)
categories = models.ManyToManyField(Category)
How can I perform a query that will give me all Article objects that are associated with any of the same categories that a given Preference object is related with?
e.g. If I have a Preference object that is related to categories "fish", "cats" and "dogs", I want a list of all Articles that are associated with any of "fish", "cats" or "dogs".
Try:
preference = Preference.objects.get(**conditions)
Article.objects.filter(categories__in = preference.categories.all())
Article.objects.filter(categories__in=myPreferenceObject.categories.all())