Filtering in ManytoManyField - python

How to make a choice only from users who are in the group created in the admin panel? In Foreign Key, this could be done via limit_choices_to, and in MtM it is not known as. Google didn't help.
class Application(models.Model):
STATUS_CHOICES = (
('In the work', 'В работе'),
('New', 'Новая'),
('Complited', 'Завершена')
)
author = models.ForeignKey(User, related_name = 'author', null = True)
title = models.CharField(max_length=50)
text = models.TextField()
room = models.CharField(max_length = 5)
published_date = models.DateField(blank=True, null=True, default = datetime.datetime.now)
status = models.CharField(max_length=15, choices=STATUS_CHOICES, default='New')
owner = models.ManyToManyField(User)
def __str__(self):
return self.title

Maybe a din't understand what you really want, but you can use limit_choices_to in a M2M field.
See the docs: https://docs.djangoproject.com/en/2.0/ref/models/fields/#manytomany-arguments

Related

django select related with 3 tables

i have 3 models in django like this:
class SlackConfigurationMode(models.Model):
MODES = (
("NORMAL", "normal"),
("ALERT", "alert"),
("DANGER", "danger")
)
mode = models.CharField(choices=MODES, default=MODES[0][0], max_length=20)
time_send_slack_notification_minute = models.IntegerField(default=0)
time_send_slack_notification_hour = models.IntegerField(default=0)
description = models.TextField(blank=True)
class WebHookConfiguration(models.Model):
webhook_url = models.CharField(max_length=100)
slack_configuration_mode = models.ForeignKey(
SlackConfigurationMode,
on_delete=models.CASCADE,
related_name='webhook_configurations'
)
class MonitorSource(models.Model):
TYPES = (
("FACEBOOK", "facebook"),
("WEBSITE", "website"),
("YOUTUBE", "youtube")
)
target = models.CharField(max_length=100)
type = models.CharField(choices=TYPES, max_length=20)
created_at = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey("auth.User", on_delete=models.CASCADE)
name = models.CharField(max_length=100)
slack_configuration = models.ForeignKey(
SlackConfigurationMode, on_delete=models.DO_NOTHING,
default=SlackConfigurationMode.objects.filter(mode="NORMAL")[0].id,
related_name='monitor_sources'
)
i want to get data of webhook_configuration and monitorsource filter by slackconfiguration by mode
i use this query:
queryset = SlackConfigurationMode.objects.select_related('webhook_configurations', 'monitor_sources').filter(
mode='HIGH'
)
but have the error:
Invalid field name(s) given in select_related: 'monitor_sources', 'webhook_configurations'. Choices are: (none)
how can i fix it, and why my query won't work, tks
Here, webhook_configurations and monitor_sources are reverese relations and hence you must use prefetch_related(...)
queryset = SlackConfigurationMode.objects \
.prefetch_related('webhook_configurations', 'monitor_sources') \
.filter(mode='HIGH')

Django Rest Framework Integrity Error at NOT NULL constraint fail

i'm trying to post a transaction via django rest framework, however it shows error in django log as below:
IntegrityError at /api/item_trans/
NOT NULL constraint failed: chemstore_itemtransaction.bin_code_id
it has no problem if I post the same data from the Django admin web.
therefore I suppose the problem has happened at DRF
any help is welcome, thank you
models.py
class BinLocation(models.Model):
bin_code = models.CharField(max_length=10, unique=True)
desc = models.CharField(max_length=50)
def __str__(self):
return self.bin_code
class Meta:
indexes = [models.Index(fields=['bin_code'])]
class ItemMaster(models.Model):
item_code = models.CharField(max_length=20, unique=True)
desc = models.CharField(max_length=50)
long_desc = models.CharField(max_length=150, blank=True)
helper_qty = models.DecimalField(max_digits=10, decimal_places=4)
unit = models.CharField(max_length=10, blank=False)
def __str__(self):
return self.item_code
class Meta:
verbose_name = "Item"
verbose_name_plural = "Items"
indexes = [models.Index(fields=['item_code'])]
class ItemTransaction(models.Model):
# trace_code YYMMDDXXXX where XXXX is random generated
trace_code = models.CharField(max_length=20, unique=False)
item_code = models.ForeignKey(
ItemMaster, on_delete=models.CASCADE, related_name='+', blank=False, null=False)
datetime = models.DateTimeField(auto_now=False, auto_now_add=False)
qty = models.DecimalField(max_digits=10, decimal_places=4)
unit = models.CharField(max_length=10, blank=False)
action = models.CharField(
max_length=1, choices=ACTION, blank=False, null=False)
bin_code = models.ForeignKey(
BinLocation, related_name='+', on_delete=models.CASCADE, blank=False, null=False)
remarks = models.TextField(blank=True)
def __str__(self):
return f"{self.trace_code} {self.datetime} {self.item_code} {dict(ACTION)[self.action]} {self.qty} {self.unit} {self.bin_code}"
serializers.py
class ItemMasterSerializer(serializers.ModelSerializer):
class Meta:
model = ItemMaster
fields = '__all__'
class ItemTransactionSerializer(serializers.ModelSerializer):
item_code = serializers.SlugRelatedField(
slug_field='item_code',
read_only=True
)
bin_code = serializers.SlugRelatedField(
slug_field='bin_code',
read_only=True,
allow_null=False
)
class Meta:
model = ItemTransaction
fields = '__all__'
You might need to use 2 fields, one for reading data and the other for creating and updating your data with its source to the main. In your case you could try this:
class ItemTransactionSerializer(serializers.ModelSerializer):
item_code_id = ItemMasterSerializer(read_only=True)
item_code = serializers.PrimaryKeyRelatedField(
queryset=ItemMaster.objects.all(),
write_only=True,
source='item_code_id'
)
bin_code_id = BinLocationSerializer(read_only=True
bin_code = serializers.PrimaryKeyRelatedField(
queryset= BinLocation.objects.all(),
write_only=True,
source='bin_code_id'
)
Since you have null=False in both of your ForeignKeys, DRF expects the corresponding ID. You seem to be getting the error NOT NULL constraint because you are not passing the ID in DRF. So you need to fix that for both bin_code_id and the item_code_id.

how to perform count for a secod foreign key in django?

i have three models Category,Post,Comment
class Category(models.Model):
class Meta:
verbose_name_plural = "Categories"
COLOR_CHOICES = (
('primary', 'Blue'),
('success', 'Green'),
('info', 'Sky Blue'),
('warning', 'Yellow'),
('danger', 'Red')
)
title = models.CharField(max_length=250, unique=True)
description = models.CharField(max_length=250)
slug = models.SlugField(max_length=200,)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
visited = models.IntegerField(default=0)
color = models.CharField(
max_length=20, default='primary', choices=COLOR_CHOICES)
class Post(models.Model):
STATUS_CHOICES = (
(True, 'Visible'),
(False, 'Hidden')
)
title = models.CharField(max_length=250)
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
body = models.TextField()
category = models.ForeignKey(
Category, on_delete=models.SET_NULL, null=True)
slug = models.SlugField(max_length=200,)
status = models.BooleanField(default=False, choices=STATUS_CHOICES)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
visited = models.IntegerField(default=0)
class Comment(models.Model):
STATUS_CHOICES = (
(True, 'Visible'),
(False, 'Hidden')
)
post = models.ForeignKey(Post, on_delete=models.CASCADE, null=True)
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.BooleanField(default=True, choices=STATUS_CHOICES)
I want to perform a query set to get categories and number of comments of each category, I can't find a good way.
I already know how to count posts for each category using annotate.
I tried :
categories = Category.objects.annotate(nb_comments=Count('post__comment'))
if you want to count number of comment that related to specific categoriy:
number_of_commemt_for_cat1=Comment.objects.filter(post__category_id=1).count()
this query say: count of comment that belong to posts that post are belong to specific category.
and here you can find count of post that related to specific category:
number_of_post_for_cat1=Post.objects.filter(category_id=1).count()
I'm with mobile so I can't explain enough or put references here for you. hope help.

nested serialization dont now create a forignkey it requires a new Object instead of 'id'

here is my model, serializer and output but when i want to create a new page it ask me to add a whole new user as its just a foreign-key it need to be a number like 1 (user id) and same in the case of categories how can i solve it.... help me please
serializers.py
class TeamMembersSerializer(serializers.ModelSerializer):
class Meta:
model = TeamMembers
fields = [
'user',
'page',
]
depth = 1
class SocialAccountsSerializer(serializers.ModelSerializer):
social = SocialCatSerializer()
class Meta:
model = SocialAccounts
fields = [
'page',
'social',
'link'
]
depth = 1
class PageImageSerializer(serializers.ModelSerializer):
class Meta:
model = PageImages
fields = [
'page',
'image',
]
depth = 1
class PageSerializer(serializers.ModelSerializer):
owner = UserSerializer()
catagory = BusinessCatSerializers()
business_type = BusinessTypeSerializer()
TeamMembers = TeamMembersSerializer(read_only=True)
social_accounts = SocialAccountsSerializer(read_only=True)
images = PageImageSerializer(read_only=True)
class Meta:
model =Page
fields = [
'id',
'owner',
'catagory',
'name',
'username',
'images',
'start_date',
'business_type',
'contect_number',
'email_address',
'website',
'TeamMembers',
'social_accounts',
'about',
'impression',
'Awards',
'Product',
'privacy_policy',
'is_active',
]
Models.py
class Page(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
catagory = models.ForeignKey(BusinessCatagories, on_delete=models.CASCADE, null=True, blank=True, default=None)
name = models.CharField(max_length=254, unique=True ,default=None, blank=True)
username = models.CharField(max_length=254, unique=True, blank=True)
start_date = models.DateTimeField(auto_now_add=True)
business_type = models.ForeignKey(BusinessType, on_delete=models.CASCADE, null=True, blank=True, default=None)
contect_number = models.CharField(max_length=254, default=None, blank=True)
email_address = models.EmailField(default=None, blank=True)
website = models.URLField(default=None, blank=True)
about = models.TextField(default=None, blank=True)
impression = models.TextField(default=None, blank=True)
Awards = models.CharField(max_length=254, default=None, blank=True)
Product = models.CharField(max_length=254, default=None, blank=True)
privacy_policy = models.URLField(default=None, blank=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
class TeamMembers(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=None, blank=True)
page = models.ForeignKey(Page, on_delete=models.CASCADE, default=None, blank=True)
def __str__(self):
return self.user.name
class SocialAccounts(models.Model):
page = models.ForeignKey(Page, on_delete=models.CASCADE, default=None, blank=True)
social = models.ForeignKey(SocialCats, on_delete=models.CASCADE, default=None, blank=True)
link = models.URLField(default=None, blank=True)
def __str__(self):
return self.link
class PageImages(models.Model):
page = models.ForeignKey(Page, on_delete=models.CASCADE, default=None, blank=True)
image = models.ImageField(default=None, blank=True, upload_to=settings.MEDIA_ROOT)
def __str__(self):
return self.page.name
output is this but i need images field TeamMember field in it but its not appearing plus it want me to add a new user instead of asking for Foreignkey "id"
What you want is to use Primary key related field. It helps you to represent the target of the relationship using its primary key.
It should look somewhat like this.
Note: Mind the typo for any name
class PageSerializer(serializers.ModelSerializer):
owner = serializers.PrimaryKeyRelatedField(queryset = User.objects.all())
catagory = serializers.PrimaryKeyRelatedField(queryset = BuisnessCat.objects.all())
business_type = BusinessTypeSerializer()
TeamMembers = TeamMembersSerializer(read_only=True)
social_accounts = SocialAccountsSerializer(read_only=True)
images = PageImageSerializer(read_only=True)
You can read more about PrimaryKeyRelatedField here.
Now whenever creating any Page, all you need to supply are primary key for owner and category.
You are looking for Writable Nested Serializer.
In short you have to override create() method of PageSerializer
class PageSerializer(serializers.ModelSerializer):
....
....
your code
def create(self, validated_data):
# pop data of every related fields like "owner", "cateagory" etc from validated_data
owner = validated_data.pop("owner")
owner = User.objects.create(**owner)
category = validated_data.pop("category")
# create or retrieve category instance ,as above
...
...
...
# finally
return Page.objects.create(**validated_data,owner=owner,category=category, and other related instances)

Django rest - Serialize nested objects

I am using Django 1.10.5 and djangorestframework 3.5.3.
I have 2 models that are related with one to many relation:
class Minisymposium(models.Model):
STATUS_CHOICES = (
('pending', 'Pending'),
('approved', 'Approved'),
('denied', 'Denied'))
id = models.AutoField(primary_key=True)
number = models.IntegerField(default=0, null=False)
title = models.CharField(max_length=100, null=False)
description = models.TextField(max_length=9000, null=False)
status = models.CharField(max_length=100, choices=STATUS_CHOICES, null=False, default='pending')
user = models.ForeignKey(User, null=False, related_name='user')
corresponding_organizer = models.ForeignKey(User, null=False, related_name='corresponding_organizer')
anticipated_abstracts = models.IntegerField(null=False)
anticipated_attendees = models.IntegerField(null=False)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{0}-{1}'.format(self.number, self.title)
class UnregisteredOrganizer(models.Model):
id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=1000, blank=False)
last_name = models.CharField(max_length=1000, blank=False)
email = models.EmailField(max_length=254, blank=True)
affiliation = models.CharField(max_length=254, help_text='(institution only)', blank=True)
phone_number = PhoneNumberField(blank=True)
minisymposium = models.ForeignKey(Minisymposium, related_name='other_organizers')
Each model have a serializer. But the problem is with Minisymposium`s serializer. Because I want to send an UnregisteredOrganizer`s ID on creating one, and get the whole object as serialized on getting a Minisymposium.
And as I see in ModelSerializer it is not possible:
class MinisymposiumSerializer(serializers.ModelSerializer):
other_organizers = UnregisteredOrganizerSerializer(many=True)
class Meta:
model = Minisymposium
fields = ('url', 'id', 'number', 'title', 'description', 'status', 'user', 'corresponding_organizer',
'anticipated_abstracts', 'anticipated_attendees', 'other_organizers', 'date')
def create(self, validated_data):
other_organizers = []
if 'other_organizers' in validated_data:
other_organizers = validated_data.pop('other_organizers')
minisymposium = Minisymposium.objects.create(**validated_data)
minisymposium.save()
for organizer in other_organizers:
UnregisteredOrganizer.objects.create(minisymposium=minisymposium, **organizer).save()
return minisymposium
How can I do that?
Thank you !
Because I want to send an UnregisteredOrganizer`s ID on creating one, and get the whole object as serialized on getting a Minisymposium.
Why have such an inconsistent API ?
The recommended option here is to set the fields on Minisymposium as read_only except for the id which should be read_only=False.
Therefore, you can get the full object when getting the data and just expect the id when post/put/patching the data. Posted JSON would look like:
{
...
"url": "whatever",
"title": "Some nice title",
"other_organizers": [{"id": 5}, {"id": 5123}]
}
Creation code would be like:
def create(self, validated_data):
other_organizers = validated_data.pop('other_organizers', [])
minisymposium = Minisymposium.objects.create(**validated_data)
minisymposium.save()
organizers = []
for organizer_id in other_organizers:
organizers .append(UnregisteredOrganizer.objects.get(id=organizer_id)
minisymposium. other_organizers = organizers
return minisymposium

Categories

Resources