Get models.ManyToManyField selected options count - django

I can't figure out how to get the manytomanyfield selected options number
my code:
class Author(models.Model):
first_name = models.CharField(max_length=30)
def __unicode__(self):
return u'%s' % (self.first_name)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
authorsnumbers = models.IntegerField()
def __unicode__(self):
return self.title
def save(self, *args, **kwargs):
if not self.id:
self.authorsnumbers = self.authors.count()
super(Event, self).save(*args, **kwargs)
if i select 2 authors, i want authorsnumber to be '2', but how?

This would probably be an easier way to do it:
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
def authorsnumbers(self):
return self.authors.count()
def __unicode__(self):
return self.title
of course you could just use book.authors.count() instead of book.authorsnumber() wherever you need it.

Related

How can I filter This in django?

I am working on a Django project (like LMS) and I want to filter Lectures by Subject in the template, I do it once but now I forgot how to do it. How can I do this?!
I want to filter it by foreign-key Subject in Lecture
Here is my models.py
from django.db import models
from django.utils.text import slugify
# Create your models here.
class Subject(models.Model):
Title = models.CharField(max_length=150)
Pic = models.ImageField(upload_to='media/')
Test = models.CharField(max_length=300, null=True, blank=True)
Slug = models.SlugField(unique=True, null=True, blank=True)
def save(self, *args, **kwargs):
self.Slug = slugify(self.Title, allow_unicode=True)
super(Subject, self).save(*args, **kwargs)
def __str__(self):
return self.Title
class Lecture(models.Model):
Subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
Title = models.CharField(max_length=150)
Video = models.CharField(max_length=300)
More_Info = models.TextField()
Audio_Lecture = models.CharField(max_length=300)
Lecture_Files = models.CharField(max_length=300)
Sheet = models.CharField(max_length=300)
Slug = models.SlugField(unique=True, null=True, blank=True)
def save(self, *args, **kwargs):
self.Slug = slugify(self.Title, allow_unicode=True)
super(Lecture, self).save(*args, **kwargs)
def __str__(self):
return self.Title
and here is my views.py
from Diploma.models import Lecture, Subject
from django.shortcuts import render
# Create your views here.
def Diploma(request):
return render(request, 'Diploma/diploma.html', context={
'sub' : Subject.objects.all(),
})
def Diploma_Subject(request, slug):
subject_Lecture = Subject.objects.all()
return render(request, 'Diploma/subject.html', context={
'subj' : subject_Lecture,
'lect' : Lecture.objects.filter(I do not know what I should write here)
})
If you want to filter the Lecture model based on the slug parameter you have to do the following:
lecture = Lecture.objects.filter(Slug=slug).first()
if lecture is not None:
# lecture.Subject, lecture.Title ...
Or if you want to filter based on the slug property in Subject model you can do the following:
lectures = Lecture.objects.filter(Subject__Slug=slug)
for lecture in lectures:
# lecture.Subject, lecture.Title ...
empty:
print('There are any lectures related')
There are many things to explain here but I tried to give you a minimal repoducible example so you can custom it to achieve your goal.
Feel free to leave a comment if you have an specific doubt about understanding it.

Problems with converting datetime to string in Django

I can't understand why this isn't working because in a Python console it works fine for me...
class Activity(models.Model):
id = models.CharField(max_length=250, primary_key=True)
description = models.CharField(max_length=255, null=False, help_text="Brief description of the activity")
start = models.DateTimeField(default=timezone.now, verbose_name="Planned start date/time", blank=True)
end = models.DateTimeField(default=timezone.now, verbose_name="Planned completion date/time", blank=True)
class Meta:
verbose_name_plural = 'Activities'
def save(self, *args, **kwargs):
self.id = "%s-%s" % (self.description, str(self.start.date()))
super(Activity, self).save(*args, **kwargs)
def __str__(self):
"""
String for representing the Model object (in Admin site etc.)
"""
return f'{self.description}'
But what I get for my self.id field is (using "xx" as description):
"xx-<built-in method date of datetime.datetime object at 0x000001FCBAAA51E0>"
Try to use strftime instead
def save(self, *args, **kwargs):
self.id = "%s-%s" % (self.description, self.start.strftime('%m/%d/%Y'))
super(Activity, self).save(*args, **kwargs)

How to call ManyToManyField in class based view

I'm just bricked here; I don’t know what is going on?
I want to do simple blog.
So as you can see below I defined ManyToManyField and set category as a many to many field and then related the name posts.
Earlier I used a function based view and I simply called it a related name like this:
example
def catdetail(request, slug):
code here
and
posts = category.pots.all() /////and this gave me all posts related to this cateogry,
But in the class based view in the category detail view I cannot call this category field from Post; all my tries are unsuccessful; errors like, category has not defined, category has no object, category or post and thing similar to that which you already know…
So my question is: how can I call this related name in Detail view in category?
Here are my models and views.py:
class Category(models.Model):
title = models.CharField(max_length=20)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse("category_detail", kwargs={"slug": self.slug})
class Tag(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.title
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
category = models.ManyToManyField(Category, related_name='posts')
title = models.CharField(max_length=100, blank=False)
slug = models.SlugField(unique=True)
body = models.TextField()
image = models.ImageField(upload_to='project/uploads/')
tag = models.ManyToManyField(Tag, related_name='tag_post')
date = models.DateTimeField(auto_now_add=True, auto_now=False)
date_mod = models.DateTimeField(auto_now=True, auto_now_add=False)
publis = models.BooleanField(default=True)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse("post_detail", kwargs={"slug": self.slug})
and views.py.
Can you tell me how to call the category field and related name here in views?
class CategoryDetail(DetailView):
model = Category
template_name = "cat_detail.html"
def get_context_data(self, *args, **kwargs):
context = super(CategoryDetail, self).get_context_data(*args, **kwargs)
context['cat'] = get_object_or_404(Category, slug=self.kwargs.get("slug"))
return context
Some help?
def get_context_data(self, *args, **kwargs):
context = super(CategoryDetail, self).get_context_data(*args, **kwargs)
posts = Category.objects.get(id=1).posts.all()
for post in posts:
post.category
print post
context['cat'] = get_object_or_404(Category, slug=self.kwargs.get("slug"))
return context
i now have this, but i got all posts whether be on that category or not

Django filter - only select postes depending on filters

**models.py**
class Category(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Gender(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Post(models.Model):
name = models.CharField(max_length=50)
categories = models.ManyToManyField(Category)
genders = models.ManyToManyField(Gender)
def __unicode__(self):
return self.name
**view.py:**
def index(request):
posts = Post.objects.filter(genders=1)
categories = Category.objects.exclude(outlet=None).filter( ?????? ).order_by('-sort'),
Now I need to select ONLY the the categories where there are postes in, depending on the given filter "genders=1"
How can I do so?
Hope you understand my issue.
.filter( post__gender=1 )

Django: Make items in ManyToMany field unavailable once it is "used"?

if this is my models.py:
class Category(models.Model):
name = models.CharField(max_length=500)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.name
def get_absolute_url(self):
return "%s" % self.slug
class Item(models.Model):
name = models.CharField(max_length=500)
slug = models.SlugField(unique=True)
category = models.ManyToManyField(Category)
def __unicode__(self):
return self.name
def get_absolute_url(self):
return "%s" % self.slug
My desired functionality is to have any Category that has already had a an Item assigned to it to not be available for any other Items. For example, if I have these Categories: { Animal, Vegetable, Mineral }, and i assign the Item "Rock" to the Category "Mineral", when I add the next Item, "Mineral" will be unavailable from the list in admin. Hopefully that makes sense, and thank you for your time.
You could specify an "available" field, something like this. And then just show "availables" to the user.
class Category(models.Model):
name = models.CharField(max_length=500)
slug = models.SlugField(unique=True)
available = models.BooleanField(default=True)
def __unicode__(self):
return self.name
def get_absolute_url(self):
return "%s" % self.slug
def save(self, force_insert=False, force_update=False, using=None):
if self.item_set.all():
self.available = False
super(Category, self).save()
If you only want each Category to be associated with a single Item, then you haven't got a ManyToMany relationship at all. You should restructure your models to make it a ForeignKey from Category to Item.