I am building a blog site and have models in respect of Category and Posts. Posts have a Many to Many relationship for Category.
class Post(models.Model):
categories = models.ManyToManyField(Category)
Everything is working fine aside from the fact that in the Category list in the template I only want to load categories that actually have posts.
If a category is empty I don't want to display it, I have tried to define a relationship in Category to Post to allow me to use something like {{ if category.posts }}. At the moment using another Many to Many field in Category is presently giving me an extra field in admin which I don't really want or feel that's needed.
How is best to navigate this relationship, or create one that's suitable?
Cheers
Kev
Django automatically creates a field on the related model of any ForeignKey or ManyToMany relationship. You can control the name of the field on the related model via the related_name option like that:
class Post(models.Model):
categories = models.ManyToManyField(Category,related_name='posts')
This way, your approach works without any additional fields. Btw, if you leave out the related_name argument, Django will create by default one with [field_name]_set.
You can use reverse relations on ManyToMany fields. In the reverse filter, you must use the related model name (if you did not use related_name attribute). So in your question you can use model name as the reverse name like:
{% if category.post %}
You can also use this in your filtering functions in views:
Category.objects.filter(post__isnull=False)
Reverse relation name must be lowercase.
Check the documentation here
Related
I'm trying to find a solution to the following problem with django models:
The app would add products to a shopping cart. The problem is that those products come from different models, and no matter where they come from, I'd like to use one ManyToManyField to incorporate them.
Suppouse I've two different kind of products from two different models:
Class ListOfProducts1(models.Model):
name= CharField()
price= IntegerField()
Class ListOfProducts2(models.Model):
name=CharField()
price=IntegerField()
The following model would be used for get the quantity and the product added(and then related to one particular order).
Here is the problem. Look to the field itemsadded, where I want to relate this field to ListOfProducts 1 and 2. I'd put both of them into the same field, but I've already know this is not possible. Just for better understanding of the problem here you have:
Class ProductsOrdered(models.Model):
itemsadded= OneToOneField(ListOfProducts1 and ListOfProducts2,on_delete=models.CASCADE)
Quantity = IntegerField()
Then the Order's model:
Class Orders(models.Model):
cart= ManyToManyField(ProductsOrdered)
The OneToOne fields can refer to only one table.
But you can use either GenericForeignKey or alternatives (which is better).
Look at this article: Avoid Django’s GenericForeignKey. It describes alternatives, such as:
nullable fields on source table
intermediate table with nullable fields
intermediate table with OneToOneFields on destination models
multi-table inheritance
multiple linked models
I have two different models:
A group model
class Group(models.Model):
(...)
users=models.ManyToManyField(users.User, related_name='trainings')
And a very standard user model.
I'm trying to write a function where it returns all of the linked groups for a given User object.
What would solve my problem is something like this:
def get_groups(user):
connected_groups = Group.objects.filter(user in users)
But that throws an error. It the thing that I am trying possible? Or should I instead create a 'linked_groups' variable within the User model?
Check the documentation here: https://docs.djangoproject.com/en/1.11/topics/db/queries/#many-to-many-relationships
Both ends of a many-to-many relationship get automatic API access to the other end. The API works just as a “backward” one-to-many relationship, above.
The only difference is in the attribute naming: The model that defines the ManyToManyField uses the attribute name of that field itself, whereas the “reverse” model uses the lowercased model name of the original model, plus '_set' (just like reverse one-to-many relationships).
For any User called u in your application, u.group_set.all() will be a queryset of all Groups with a many-to-many relationship to that user. Since you have defined a related_name you can use the more readable syntax u.trainings.all().
I wanted to get a list of objects associated to model A by ManyToMany with model B, e.g. diners (A) confirmed to attend a meal(B). But I'm not sure what getter I should use. I actually wanted to do this to show the associated objects in the admin panel. The method included beneath was one failed attempt I made.
class Meal(models.Model):
diners = models.ManyToManyField(User, through='Attendance', related_name="eating", blank=True)
def diners(self):
return self.eating
Can you help?
Thanks
As ilvar suggested, remove diners method and use self.diners.all() to get objects inside Meal methods. related_name='eating' is for fetching attended meals of a user, reversely.
I arrived at this page with the same problem as OP. I ended up simply removing the reference to the ManyToMany field in list_display in my admin model. The result: on the admin page for that app, under the ManyToMany field name, appeared a nicely formatted multi-selection list widget with the possible values for my ManyToMany relationship shown.
So the solution was to remove the reference in list_display and let Django handle it. This is with Django 1.4.3.
How do I travel through multiple foreign keys in Django? I've tried everything I can think of from the django docs, but I'm obviously missed something (extreme newbie). I have models for scientists, experiments, and theories.
If I want to look at a particular Theory (let's call it 'relativity') and get a list of all of the emails of scientists working on it (kept in the normal django user model), how do I do this?
class Experiment(models.Model)
experimenter = models.ForeignKey(Scientist)
theory = models.ForeignKey(Theory)
class Theory(models.Model)
name = models.CharField(max_length=100)
class Scientist(models.Model)
user = models.ForeignKey(User, unique=True)
institution = models.CharField(max_length=20, null=True, blank=True)
These are simplified versions of my models that I rewrote, so there are probably some errors in it, but the relationships are correct.
I've tried every kind of combinations of select_related(), get(), filter() but can't figure it out. Thanks in advance for your help!
User.objects.filter(scientist__experiment__theory__name=u'relativity')
Take a look at the Django documentation section about Lookups that span relationships. The net takeaway is:
To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.
Ignacio's answer shows an example of using the double underscores on field names to span a relationship.
The other relevant portion of Django's documentation would be the Related objects section. Relationships in Django are asymmetrical in the way they are accessed. Forward/normal relationships are accessed as attributes of the models. Backward relationships are accessed:
Django also creates API accessors for the "other" side of the relationship -- the link from the related model to the model that defines the relationship. For example, a Blog object b has access to a list of all related Entry objects via the entry_set attribute: b.entry_set.all().
A while back I made a Model class. I made several ModelForms for it and it worked beautifully.
I recently had to add another optional (blank=True, null=True) field to it so we can store some relationship data between Users. It's essentially a referral system.
The problem is adding this new field has meant the referral field shows up where I haven't changed the ModelForms to exclude it. Normally this would just mean an extra 10 minutes going through and excluding them but in this case, due to project management politics out of my control, I only have control over the Models for this application.
Can I either:
Set the field to auto-exclude?
Set it so it renders as a hidden (acceptable if not perfect)?
If you have access to the template you could render it as a hidden field with the following code:
{{ form.field_name.as_hidden }}
instead of the standard:
{{ form.field_name }}
from the docs on Using a subset of fields on the form:
Set editable=False on the model field. As a result, any form created from the model via ModelForm will not include that field.
You could define a custom model field subclass and override the formfield() method to return a field with a HiddenInput widget. See the documentation for custom fields.
Though you mentioned that you cannot use exclusion in your case, I think others who come across this answer (like myself, based on the title) may find it helpful.
It is possible to selectively hide fields using exclude in ModelAdmin, here is a snippet from something I'm working on:
class ItemsAdmin(admin.ModelAdmin):
form = ItemsForm
actions = None
list_display = ('item_id', 'item_type', 'item_title', 'item_size', 'item_color',)
search_fields = ('item_id', 'item_title',)
inlines = [ImageInline,]
readonly_fields = ('disable_add_date','disable_remove_date',)
exclude = ('add_date', 'remove_date',)
###.............