In my Django app, I have two models: Publications and Tags. These two models have a many to many relationship:
class Tag(models.Model):
title = models.CharField(max_length=50,)
class Publication(models.Model):
title = models.CharField(max_length=200,)
tags = models.ManyToManyField(Tag, blank=True, related_name="publications", null=True)
On the admin site, I'd like to be able to make bulk edits to the publication objects. Specifically, I'd like to be able to update the tags for a group of publications.
For example, if I choose from the publications page, "publication 1, publication 2, and publication 3," and create an action that says "change_tags" and I hit go, I see the list of tags in the database and I can select from that list and add the chosen tags to all three publications.
I don't know if there is a way to do this. I checked the Django docs on adding actions: https://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#ref-contrib-admin-actions but the example given doesn't address the complexity of what I am trying to do.
After some further investigation in the Django docs, I discovered that I can add an action that directs the admin user to an intermediate page that I can create to make whatever edits are necessary. https://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#actions-that-provide-intermediate-pages
Related
I've been reading through the Django documentation and looking over some of the other answers on the site for a couple of hours now, yet I still can't get it to sink in. I know this isn't Django specific, but the examples I use will be from a Django project.
My question boils down to when is it appropriate to use each:
Many-to-many relationships
Many-to-one relationships
One-to-one relationships
One-to-one, more or less makes sense to me.
Now for the other two. While I understand the differences between them in isolation, when it comes to using them practically in a project, I get confused. Here is an example:
class User(AbstractUser):
pass
class Listing(models.Model):
title = models.CharField(max_length=64)
description = models.TextField()
class Watchlist(models.Model):
user = models.ForeignKey(User, related_name='watchlist', on_delete=models.CASCADE)
item = models.ManyToManyField(Listing)
class Comment(models.Model):
user = models.ForeignKey(User, related_name='comments', on_delete=models.SET_NULL)
comment = models.TextField()
Would this be the correct use of Many-to-one(ForeignKey) and Many-to-many?
Should Watchlist.item be a ForeignKey? Or is M2M correct?
Wouldn't it simplify to make the 'Watchlist' part of the User class? (give them an empty list to populate with listing ID's)
Why is Watchlist.user not a One-to-one relationship, if each watchlist belongs to a single user, and a user can only have one list?
Apologies for my stupidity, I just can't get this to sink in!
Thank you.
edit: Context, the models are from a 'learning' project I was working on intended to be an auction site, similar to eBay. The watchlist is sort of a 'wish' list... for the user to watch an item, not for site to watch a user!
To explain it simply these django-models or objects represents tables in your database and the fields are like the columns in them. So with a one-to-one relation you can only have one row in one table relating to one row in another table. For example one user in the user table (represented by one row) can only relate to one row in a profile table. But your user can have many comments, so this would be a one-to-many/foreignkey relation (if you set unique=true on a fk, it will in practice function as 1:1). If the users can collaborate on writing comments, or for example as here on stackoverflow where users can edit other users comments, that would be a many-to-many relation.
Database design can be complicated/complex, especially using an ORM without basic knowledge of SQL and how it all works beneath. In general it requires a bit of planning even for a simple application.
I am creating a website and have two forms. The database I have has authors and titles. What I want to do is when I click the author in my choice field, I want the titles to be filtered so the user can only select those. How would I do this?
class ArticleForm(forms.ModelForm):
author = forms.ModelMultipleChoiceField(queryset=Article.objects.all())
title = forms.ModelMultipleChoiceField(queryset=Article.objects.filter(author=author))
class Meta:
model = Article
fields = ('author','title')
When I click the author name, the title still remains blank. What should I do?
Below is my model
class Article (models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=200)
First you need a relation between the article and author. If you have models like this:
class Author(models.Model):
name = models.CharField(max_length=200)
class Article(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author)
Than an Article belongs to an Author and a Author can have many Articles.
A modelForm based on the Author model lets you add (or modify) an author. A modelForm based on Article lets you add (or modify) an article. Thats all very useful but not in this case. We need a normal form with ModelChoiceFields to select author and article:
class ArticleForm(forms.Form):
author = forms.ModelChoiceField(queryset=Author.objects.all())
article = forms.ModelChoiceField(queryset=Article.objects.all())
This form will have a select widget for both author and article field. It let's you select one of each. It will render all authors and all articles to template. That's okay if you have a few, but will be problematic with many entries.
The next part is to filter the article choices. The answer to this is a bit harder. Because it depends on your project requirements.
You might want to write some JavaScript to filter the select fields
based on author.
You might want to add a validator for fields that
depend on each other.
You might not want to load all articles in
advance and might want to use Ajax techniques to load the articles
belonging to an author.
You might want to use the FormWizard to split your form in multiple pages/steps.
...
I am using Django 1.6. In the "Add" interface for one of my models, I have a field that is a foreign key to another model. Therefore it is displayed as a dropdown box containing the string representation of the second model. I want to be able to split it up into its constituent fields instead. Is there a way to do this?
ie. For example, in my "Add" screen for the model for "User", I have a field "Favourite Book". "Book" is displayed as a dropdown menu with string representations "Title, Author" for all books in the database, and I want to be able to display two dropdown menus instead, one for each of the fields Title and Author.
EDIT
This isn't my actual application. In my application, there is the added feature that all Author-Title combinations are possible (obviously this is not really the case for this example), so it would be very useful to be able to select the Title and Author separately rather than from a giant drop down menu containing all possible permutations.
What you are saying doesn't really make sense. The foreign key dropdown represents all Book objects in your database and allows you to create a relationship between your User and the particular Book that you select, i.e. that particular title/author combination. You can't select title and author independently as they are fields in a single Book and represent that particular Book (not to mention that title is a text field)
You could use a Django Admin Inline. You can see an example of inlines in this question:
This would allow you to relate numerous Books to a single User within the same admin page.
# models.py
from django.db import models
class User(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=100)
# admin.py
from django.contrib import admin
class BookInline(admin.StackedInline):
model = Book
class UserInline(admin.ModelAdmin):
inlines = [
BookInline,
]
So I am trying to implement a user favorites system in Django. I need to store the time at which a Gallery object was favorited, so I am using Django's many to many through pattern. As you can see below I have a Gallery object which has the many to many relationship to Users who have favorited it, and the Favorite object which has a many to one with both User and Gallery. I would like to do some things like display a page with all the user's favorites on it, query a users favorites to see if a certain Gallery is in them, etc. So basically be able to get the galleries a certain user has favorited. What is the easiest way to do this with the ORM, or is this something I would need to write raw SQL for?
class Gallery(models.Model):
favoriters = models.ManyToManyField(
User, through='Favorite', null=True, related_name="favoriters")
def __unicode__(self):
return self.name
class Favorite(models.Model):
user = models.ForeignKey(User)
gallery = models.ForeignKey(Gallery)
date = models.DateField(auto_now_add=True)
Thanks.
You can easily do this with the Django ORM.
display a page with all the user's favorites on it
user.favoriters.all() # though that is not a good related_name
query a user's favorites to see if a certain Gallery is in them
if user.favoriters.filter(pk=my_gallery.pk).exists():
pass
See the documentation for more examples.
I'm trying to mimic the functionality from the Django Admin tool where it allows you to add objects for foreign keys (a little plus icon next to a dropdown). For example, let's say I have the following:
class Author(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Blog(models.Model):
name = models.CharField(max_length=50)
author = models.ForeignKey('Author')
When I go to add my first Blog using a ModelForm for Blog, it shows a dropdown next to Author. However, I have no Authors in the system so that dropdown is empty. In the admin tool, I believe it puts a little "+" icon next to the dropdown so you can quickly and efficiently add a record to the dropdown by opening up a popup.
That is extremely useful, and so I'd like to mimic it in my own app using ModelForms. Is that also built into Django's ModelForms? If so, how do I use it? I can't seem to find anything in the documentation.
You will need to work with: django.contrib.admin.widgets.RelatedFieldWidgetWrapper
This post certainly will guide you:
Django admin - How can I add the green plus sign for Many-to-many Field in custom admin form