Django ModelForm - Allowing adds for ForeignKey - python

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

Related

Foreign key model in Django Admin

I have two user roles in Django:
Commercials
Sellers
I have created two models, Seller Model has a ForeignKey field to Commercials (every seller has a commercial related to). When I register the models in admin I can create Commercials and related sellers using StackedInline, TabularInline etc.
The problem I have is I need to associate users to this models in order to authenticate, login, etc. In admin I need to create a user (in an inline way, not dropdown box)
This is my code:
In models.py:
class Commercial(models.Model):
name = models.CharField(max_length=255, null=True)
user = models.OneToOneField(User, null=True)
class Seller(models.Model):
name = models.CharField(max_length=255, null=True)
commercial = models.ForeignKey('Commercial')
user = models.OneToOneField(User, null=True)
In admin.py:
class SellerAdmin(admin.StackedInline):
model = Seller
extra = 1
class CommercialAdmin(admin.ModelAdmin):
inlines = [SellerAdmin]
admin.site.register(Commercial, CommercialAdmin)
I need to edit, create, users etc. related to this models inline not in a modal window, Is there any way?
There is no way to make a reverse relation (so to say) in the form of Inlines. The Django admin panel doesn't have that ability by default.
What you could do is unregister the default UserAdmin, create a new Admin panel by inheriting the original one, and add this Seller as an Inline. There is still the issue that Django doesn't support multiple inlines, hence, you will not be able to use the Commercial model in the same admin page.
To fix that, you could refer to this information from the doc which shows how to overwrite the automatically created ModelForm for a particular ModelAdmin.
This will however not be that helpful as they are a lot of work. I would rather suggest implementing a workaround in how your application is used, rather than complicating it this much. Depends on the needs of the project, whether you need to go through this much trouble
Django nested inlines library might help you.

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.

Creating front-end forms like in Django Admin

I was curious if there was a way to replicate the Django admin interface - specifically the forms when adding an object - in the front end... Here's my scenario:
class Area(models.Model):
name = models.CharField(max_length=100)
class SubArea(models.Model):
name = models.CharField(max_length=100)
area = models.ForeignKey(Area)
class Product(models.Model):
name = models.CharField(max_length=150)
area = models.ForeignKey(Area, null=True, blank=True)
subarea = models.ForeignKey(SubArea, null=True, blank=True)
So If I setup a form in the frontend for the Product model, I have no way of adding Area or SubArea objects. In the Django admin, however, I'm able to easily add these objects by clicking the "+" next to the fields.
I am looking for the easiest possible solution (while still being secure) to allow for fronted creating of the Foreign Keys without having to setup separate forms. Not sure if that is even possible, but wanted to reach out to the community for advice.
Thanks!
J
Django admin makes extensive use of formsets, see below:
https://docs.djangoproject.com/en/1.6/topics/forms/formsets/
Regarding your query with adding the '+' a la Django admin, you can acheive this with the RelatedFieldWidgetWrapper which you can find here.
According to my experience the easiest way of adding, editing, updating corresponding(related) items on a Form on the front-end, same way like in the django-Admin, is using "django-addanother" which you can use from here. Easy, fast and clean solution on this problem and it works with Django 1.11 too. And it has good documentation, demo also.
django-form-admin (.. let enter more characters stackoverflow needs 30 for answer)

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

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

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