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

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.

Related

Django: using __str__ with a foreignkey in order to return an item

I am simply trying to override the str method to return something from a foreign key. A snippet of my models is as follows:
class Product(models.Model):
name = models.CharField(max_length=120)
shortened_name = models.CharField(max_length=50)
date_of_creation = models.CharField(max_length=20, null=True)
history = models.CharField(max_length=255)
price = models.DecimalField(max_digits=9, decimal_places=2)
style = models.CharField(max_length=50)
artist = models.ForeignKey(Artist, on_delete=models.SET_NULL, null=True)
image = models.ImageField(upload_to='images', null=True)
slug = models.SlugField()
def get_absolute_url(self):
return reverse('product', args=[self.slug])
def save(self, *args, **kwargs):
self.slug = slugify(self.shortened_name)
super().save(*args, **kwargs)
def get_add_to_cart_url(self):
return reverse('add_to_cart', kwargs={
'slug': self.slug
})
class ShoppingCartOrderItem(models.Model):
item = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
def __str__(self):
return self.product.name
After adding the item to my shopping cart, in the admin panel when trying to view the specific item I get an AttributeError: 'ShoppingCartOrderItem' object has no attribute 'product'. Based on my googling so far I don't see why this isn't working. I have even tried str(self.product.name) but still the same error produces. I am unsure what I am doing wrong. Any help or suggestions is greatly appreciated!

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

Get models.ManyToManyField selected options count

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.

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 model filter, depending on exsisteing relation

How can I ONLY the categories where there is at least one "Post" related??, hope it makes sense!?
**models.py**
class Category(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)
def __unicode__(self):
return self.name
**view.py:**
def index(request):
categories = category.objects.filter( ??? )
How can I ONLY the categories where there is at least one "Post" related??, hope it makes sense!?
categories = Category.objects.exclude(post=None)
models.py
class Category(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Post(models.Model):
category = models.ForeignKey(Category)
name = models.CharField(max_length=50)
genders = models.ManyToManyField(Gender)
def __unicode__(self):
return self.name
views.py
def index(request):
categories = Category.objects.filter(post__isnull=False)
Each foreignkey have a reverse relation to its parent model, so ypu must place a foreignkey to your Post model and post__isnull=False will return only categories that have a reverse relation to some posts...