Splitting field in Django admin "Add" interface into its constituent fields - python

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,
]

Related

Django multiple-choice field of options in database

I am designing a model, view and template for my news aggregation app. I want the template to offer the user a multiple-choice field form with options from the database. How do I design this in my model?
I was reading the Django documentation about ManyToManyField (the one with journalists and articles) but I don't think that is quite the right relationship because in my case, "articles" can exist without a journalist and journalist without an article.
I have Users. I have Streams. Streams is a collection of news sites a user can sign up to follow and see aggregated headline snippets, such as from CNN,Twitter, Google News, etc etc. A Stream can exist with no Users. A Stream can have many Users. A User can have no Streams, in fact all user accounts start in my app with no Streams until they choose one. A User can have many Streams.
In the template, I want to create a form with the list of all the Stream options in the database (this will likely change as I ad more options in the future). When a User selects a Stream, it will be added to their dashboard view. They can add and delete Streams. However, there is only 1 Twitter, 1 Google News, etc source. I can't use the typical choices option in the User model, I want it to be "dynamic" and pull straight from the Streams database.
This is what I have now but I know it's not right:
streams/models.py
from django.db import models
from django.contrib.auth.models import User
class Stream(models.Model):
user = models.ManyToManyField(User, blank=True, null=True)
name = models.CharField(max_length=30)
user/models.py
from django.db import models
class User(models.Model):
name = models.CharField(max_length=30)
'''''
#TODO: make this dynamic, streams is pulling from Streams model
streams = (
('Google News'),
('Yahoo News'),
('Twitter'),
('CNN'),
('New York Times'),
('NBC News'),
('Huffington Post')
)
stream_choices = models.CharField(max_length=9, choices=streams)
'''''
Just add one model for list of streams and another model for user selected streams
class Stream(models.Model):
name = models.CharField(max_length=50)
class UserStream(models.Model):
user = models.ForeignKey(User)
name = models.ForeignKey(Stream)
That's it. Insert possible streams to Stream model and user selected streams to UserStream model.
The ManyToManyField already implicitly creates the 'intermediary table' described in the accepted answer. As per the documentation:
Behind the scenes, Django creates an intermediary join table to
represent the many-to-many relationship.
You can pass a callable to the choices field of the ChoicesField which you display to the user, allowing the list of available choices to be determined dynamically when the form is generated.
The list of valid choices in the User<->Stream relationship is already constrained by the relationship, so there's no benefit in specifying the available choices on the model field.

Using forms in Django

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.
...

Add entries to the choices of a field through the admin site?

I have a model with some default entries in a choices field. I was wondering if it was possible for the admin to add and remove entries to the choices from the admin site. The only other option I see at the moment is to have a separate table for the entries, but the spec specifically says to only use one table and I'm fairly new to Django. The current model code is very basic, and I haven't added any forms to admin.py, only registered my model. Example code:
class Contact(models.Model):
#some other fields here...
...
TYPES = (
('op1','option1'),
('op2','option2'),
('op3','option3')
)
option = models.CharField(
max_length=3,
choices=TYPES,
default='op1'
)
I want the super user to be able to click an add/remove type button on the admin page to open a new box which will allow them to edit the possible types.
Turns out I had to make a new model after all. it's fine, the admin site works as it needs to.

Django ModelForm - Allowing adds for ForeignKey

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

Django Admin Bulk Edit on Many to Many Relationship

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

Categories

Resources