Including models inside Inline Models in Django - python

Is it possible to add models inside inline models in Django?
I have 3 models as below
class Platform(models.Model):
platformId = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
class Partner(models.Model):
platform = models.ForeignKey(Platform,on_delete=models.CASCADE)
name = models.CharField(max_length=100)
description = models.TextField()
class Inventory(models.Model):
partner = models.ForeignKey(Partner, on_delete=models.CASCADE)
display = models.BooleanField(default=False)
In admin, I added Partner as inline in Platform as below
from django.contrib import admin
from .models import Platform, Partner, Inventory
class PartnerInline(admin.StackedInline):
model = Partner
extra = 1
class InventoryInline(admin.StackedInline):
model = Inventory
extra = 1
class PlatformAdmin(admin.ModelAdmin):
inlines = [
PartnerInline
]
Now what I want is to add the InventoryInline as part of the partner. Is it Possible?
That means when I add a partner I want to add inventory for each partner.
Inline inside and inline. Is this possible?
Or is there any other way to achieve this?
I am new to Django

Related

How to use Admin Model as foreign key in django?

I try to develop a relationship as
One admin can add one or many subscription plans.
I try this but not worked
from django.db import models
from django.contrib import admin
class SubscriptionPlansModel(models.Model):
title = models.CharField(max_length=50)
price = models.IntegerField()
duraion = models.IntegerField()
admin = models.ForeignKey(admin,on_delete=models.CASCADE)
you literally making a ForeignKey relation with a module not a db model
Just create "Admin" class in models file. Then, use it as foreign key.
E.g.
class Admin(admin.ModelAdmin):
pass
class SubscriptionPlansModel(models.Model):
title = models.CharField(max_length=50)
price = models.IntegerField()
duraion = models.IntegerField()
admin = models.ForeignKey(admin,on_delete=models.CASCADE)

How to edit a property in Django Admin?

I have a model with an attribute that is connected to another model as follow:
class Book(models.Model):
synced = models.OneToOneField('SyncedBook'
related_name='internal',
on_delete=models.CASCADE)
# some more attributes here...
#property
def book_address(self)
return self.synced.book_address
However, the book_address is a also a FK in the SyncedBook table as follow:
book_address = models.ForeignKey('Address', db_index=True, null=True, blank=True,
related_name='address_book', on_delete=models.PROTECT)
I don't know and understand how to be able to edit the book_address through the Django admin page in class BookingAdmin(admin.ModelAdmin), even though I have read over the documentation. At first I have the attribute as readonly, but now I want to be able to edit it and save the new address from the Address table. Is there a way to make it happen through the class BookingAdmin(admin.ModelAdmin) and how? Any example and solution would be appreciate
Model properties are typically used for presenting logically defined data for a particular model instance and not necessarily storing data on the model instance itself.
An example of when to use a model property is as follows:
# Defines a product instance
class Product(model.Models):
name = models.CharField(max_length=100)
description = models.TextField()
active = models.BooleanField(default=True)
cost = models.DecimalField(max_digits=5, decimal_places=2)
price = models.DecimalField(max_digits=5, decimal_places=2)
# calculate profits on product
#property
def profit(self)
p = self.price - self.cost
return p
In your case, you are trying to actually be able to modify data against a related model instance within the django admin. To me this sounds like more specifically an Inline (click here for documentation)
So in your case, you would need to create something like the following to your admin.py file:
class SyncedBookInline(admin.TabularInline):
model = BookInline
#admin.Register(Book)
class BookAdmin(admin.ModelAdmin):
# all your model admin settings
inlines = [SyncedBookInline]
Additional Info:
The Inline solution should still work for you. Please see the working code listed below:
models.py:
from django.db import models
class Hero(models.Model):
name = models.CharField(max_length=50)
class HeroAcquaintance(models.Model):
name = models.CharField(max_length=50)
hero = models.OneToOneField(Hero, on_delete=models.CASCADE)
admin.py:
from django.contrib import admin
from .models import *
class HeroAcquaintanceInline(admin.TabularInline):
model = HeroAcquaintance
#admin.register(Hero)
class HeroAdmin(admin.ModelAdmin):
list_display = (
'name',
)
inlines = [HeroAcquaintanceInline]
#admin.register(HeroAcquaintance)
class HeroAcquaintanceAdmin(admin.ModelAdmin):
list_display = (
'name',
)
Screenshot:

How can I display the contents of a related table within the Django admin change form?

I'm new to programming, Python, and Django, so your patience is appreciated. I have been writing a practice application in Django for storing cooking recipes. I have two models:
class Recipe(models.Model):
recipe_name = models.CharField(max_length=30)
recipe_instructions = models.TextField()
recipe_whyitworks = models.TextField(verbose_name="Why It Works")
recipe_date = models.DateField()
def __str__(self):
return self.recipe_name
def was_published_recently(self):
return self.recipe_date >= timezone.now() -datetime.timedelta(days=5)
class Ingredient(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
ingredient_name = models.CharField(max_length=30)
ingredient_qty = models.DecimalField(verbose_name='Quantity', max_digits=3, decimal_places=2)
ingredient_uom = models.CharField(verbose_name='Unit of Measure', max_length=15)
def __str__(self):
return self.ingredient_name
I have admin set to be able to edit either table:
from django.contrib import admin
# Register your models here.
from .models import Recipe, Ingredient
admin.site.register(Recipe)
admin.site.register(Ingredient)
What I want to do is when I click on an "Ingredient" I would like it to show all previous ingredients added to the recipe, along with the quantity and unit of measure for each in a table, in addition to the fields which allow me to add a new one. Thanks in advance for your help!
You can add inlines like this:
admin.py
from django.contrib import admin
class IngredientInline(admin.TabularInline):
model = Ingredient
class RecipeAdmin(admin.ModelAdmin):
inlines = [
IngredientInline,
]
admin.site.register(Recipe, RecipeAdmin)
admin.site.register(Ingredient)

With Django, representing foreignkeys in Admin

Building a generic app to practice learning with Django.
Two classes in Models:
class HouseInformation(models.Model):
house_name = models.CharField(max_length=200)
house_type = models.CharField(max_length=40)
address = models.CharField(max_length=200)
latitude = models.CharField(max_length=200)
longitude = models.CharField(max_length=200)
def __str__(self):
return self.house_name
class HouseReport(models.Model):
the_house = models.ForeignKey(HouseInformation)
visit_date = models.DateField()
In Admin view, I'd like to see a list of the houses with the dates they were visited. The admin.py so far is like so, and its not working:
from django.contrib import admin
from housing.models import HouseInformation
from housing.models import HouseReport
class HouseReport(admin.ModelAdmin)
list_display = ('the_house')
admin.site.register(HouseInformation, HouseReport)
I hope the one-to-many is represented correctly (one house can have many visits).
The problem is the missing ::
class HouseReport(admin.ModelAdmin):
^
Speaking about the task you've initially wanted to solve, check the InlineModelAdmin classes:
The admin interface has the ability to edit models on the same page as
a parent model. These are called inlines.
Add this to the admin.py:
from django.contrib import admin
from housing.models import HouseInformation, HouseReport
class HouseReportInline(admin.TabularInline):
model = HouseReport
class HouseAdmin(admin.ModelAdmin):
inlines = [
HouseReportInline,
]
admin.site.register(HouseInformation, HouseAdmin)
And you will see the House information and all of the HouseReports associated with a House on the House admin page.
You forgot the : after the class definition in line 5
class HouseReport(admin.ModelAdmin):
And you have to write
...
list_display = ('the_house',)
...
notice the trailing comma? It tells python, that it should create a tuple

Django reverse foreign key in admin

I have a Django related question about foreign keys in the admin panel. I'm facing the following situation:
class Driver(models.Model):
name = models.CharField(max_length=200)
executable = models.CharField(max_length=200)
class Device(models.Model):
name = models.CharField(max_length=200)
bound_driver = models.ForeignKey(Driver)
class DriverAssignment(models.Model):
device = models.ForeignKey(Device)
driver = models.ForeignKey(Driver)
Every device needs to have a bound driver (which it uses). DriverAssignment should be the table which shows which driver can be used by which device. So one device can have multiple possibilities of drivers which can be bound. Now i would like to have a dropdown on my admin panel showing all possible drivers for a specific device to select the 'bound_driver'.
How can i do this in Django? This is probably an easy thing for an experienced Django guy. I hope someone can give me a hint since i'm kind of new to Django. Thanks a lot!
For Django >1.8
Use the InlineModelAdmin (docs for 2.2) as explained there:
models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
admin.py
from django.contrib import admin
class BookInline(admin.TabularInline):
model = Book
class AuthorAdmin(admin.ModelAdmin):
inlines = [
BookInline,
]
Change your model Structure to This:
class Driver(models.Model):
name = models.CharField(max_length=200)
executable = models.CharField(max_length=200)
class Device(models.Model):
name = models.CharField(max_length=200)
bound_driver = models.ForeignKey(Driver, related_name="bound_to")
available_drivers = models.ManyToManyfield(Driver)
ManyToManyField would do the same work as DriverAssignment Table.
You can add Available drivers in Available drivers field.
But then You would also Want that bound_driver is one of the Available Drivers. This validation you will have to do in forms. For that you have to over-ride Admin forms. See links
Links of Reference:
ManytoMany field: https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ManyToManyField
Model Admin (to over-ride admin functionality):
https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#modeladmin-objects
You will have to spend some time reading and implementing if you want ot learn more. :)
OR
If you want to go with the same structure, than you will have to over-ride the form in ModelAdmin see here and Provide you custom form, which will be something like this:
class CustomForm(ModelForm)
bound_driver = forms.ModelChoiceField(queryset = <your custom queryset that returns only available drivers>, ...)
class Meta:
model = Device
https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form
There is a snippet for inverse inlines. If you still need it you may try this:
https://gist.github.com/mzbyszewska/8b6afc312b024832aa85
It has been used by me for OneToOneField in django 1.5 and 1.6. Unfortunately I did not test it for ForeignKeyField, but the one of the previous users claims that it works for ForeignKeyField either.
The best description of the snippet is contained in it. The Person class is your DriverAssignment class and Device correspond to the Address class in the example below:
Example:
from django.db import models
class Address(models.Model):
street = models.CharField(max_length = 255)
zipcode = models.CharField(max_length = 10)
city = models.CharField(max_length = 255)
class Person(models.Model):
name = models.CharField(max_length = 255)
business_addr = models.ForeignKey(Address,
related_name = 'business_addr')
home_addr = models.OneToOneField(Address, related_name = 'home_addr')
other_addr = models.OneToOneField(Address, related_name = 'other_addr')
You use reverseadmin in the following way:
from django.contrib import admin
from django.db import models
from models import Person
from reverseadmin import ReverseModelAdmin
class AddressForm(models.Form):
pass
class PersonAdmin(ReverseModelAdmin):
inline_type = 'tabular'
inline_reverse = ('business_addr', ('home_addr', AddressForm), ('other_addr' (
'form': OtherForm
'exclude': ()
)))
admin.site.register(Person, PersonAdmin)
inline_type can be either "tabular" or "stacked" for tabular and
stacked inlines respectively.

Categories

Resources