Django populate choice from ForeignKey - python

In the following code I am trying to have the Owner form with a drop-down menu that has car brands from the Car model as choices. I do get the drop-down menu but the elements listed as "Car object" each, instead of the brands. How do I get the brands from the Car model into the menu? Thanks.
models.py
from django.db import models
class Car(models.Model):
brand = models.CharField(max_length=20)
class Owner(models.Model):
name = models.CharField(max_length=20)
car_brand = models.ForeignKey(Car)
forms.py
from django.forms import ModelForm, ModelChoiceField
from app.models import Owner
class OwnerForm(ModelForm):
car_brand = ModelChoiceField(queryset=Car.objects.all())
class Meta():
model = Owner

Add a __unicode__ function to your model definition.
class Car(models.Model):
brand = models.CharField(max_length=20)
def __unicode__(self):
return u'%s' % (self.brand)
This way you can control what to be displayed

Thanks so much for sharing this, it helped me! In Django 1.8, try:
brand = models.ForeignKey(Car)
Dont put car_ in front of the foreign key

Related

Sort a displayed column defined by a custom model method in the Django admin interface

I want to be able to sort a table column defined using a custom method in the Django admin.
I narrowed down the problem to this simple example in Django:
models.py:
from django.db import models
class MyObject(models.Model):
name = models.CharField(_("name"), max_length=255)
layers = models.URLField(_("Layers"), blank=True, max_length=1024)
choices = models.TextField(
verbose_name=_("Choice values"),
blank=True,
help_text=_("Enter your choice"),
)
class Meta:
verbose_name = _("Object config")
verbose_name_plural = _("Objects config")
def __str__(self): # my custom method
return self.name
and admin.py:
from django import forms
from django.contrib import admin
class MyObjectAdminForm(forms.ModelForm):
"""Form"""
class Meta:
model = models.MyObject
fields = "__all__"
help_texts = {
"layers": "URL for the layers",
}
class MyObjectAdmin(admin.ModelAdmin):
form = MyObjectAdminForm
list_filter = ["name",]
search_fields = ["name",]
# I want the first column (__str__) to be sortable in the admin interface:
list_display = ["__str__", ...] # the ... represent some other DB fields
but for the moment I cannot sort that first column (it is grayed out, I cannot click on its title):
So how could I sort the first column in this admin table as defined by the __str__() method of the MyObject model? (please note that I cannot change the model itself. I'm also brand new to Django, so don't hesitate to detail your answer as if you were speaking to a kid.)

Django related model not updating related object in admin

I have 2 models that look like this:
models.py
class Client(models.Model):
deal = models.ManyToManyField('Deal', related_name="clients")
class Deal(models.Model):
client = models.ManyToManyField(Client, related_name="deals")
Then in the admin, I have inlined the related models to make it easy to make changes regardless of the object type you have open.
admin.py
class ClientInline(admin.TabularInline):
model = Deal.client.through
class DealAdmin(admin.ModelAdmin):
inlines = [ClientInline]
class DealInline(admin.TabularInline):
model = Client.deal.through
class ClientAdmin(admin.ModelAdmin):
inlines = [DealInline]
However, if you add a Client to a Deal and then open the Client detail page, the corresponding deal does not appear. Is there something I'm not connecting?
It is enough to have relation define only in one model. Otherwise you'll have 2 separate tables for separate ManyToMany relation: ClientDeal and DealClient.
What you need to do is to choose which one you need to leave. And probably update Admin inlines according to Django Admin documentation
class Client(models.Model):
deals = models.ManyToManyField('Deal', related_name="clients")
class Deal(models.Model):
pass
Yes, If you're using models.manytoMany() , you have to put it only in one model. no the two
But there's a very good attribute you should use: through
with through attribute you can create a intermediate model. here there's an example:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=200)
groups = models.ManyToManyField('Group', through='GroupMember', related_name='people')
class Meta:
ordering = ['name']
def __unicode__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=200)
class Meta:
ordering = ['name']
def __unicode__(self):
return self.name
class GroupMember(models.Model):
person = models.ForeignKey(Person, related_name='membership')
group = models.ForeignKey(Group, related_name='membership')
type = models.CharField(max_length=100)
def __unicode__(self):
return "%s is in group %s (as %s)" % (self.person, self.group, self.type))
later, you can use your inline admin class!
I just tested this an you were actually really close.
First, #wowkin2 said, you don't want to define a ManyToManyField in both models so I would probably just define it in your Deal model.
Second, replace this:
class DealInline(admin.TabularInline):
model = Client.deal.through
with this:
class DealInline(admin.TabularInline):
model = Deal.client.through
And everything should work.
So, this is what your files should now look like:
models.py
class Deal(models.Model):
client = models.ManyToManyField(Client, related_name="deals")
admin.py
class ClientInline(admin.TabularInline):
model = Deal.client.through
class DealAdmin(admin.ModelAdmin):
inlines = [ClientInline]
class DealInline(admin.TabularInline):
model = Deal.client.through
class ClientAdmin(admin.ModelAdmin):
inlines = [DealInline]

Django Nested Serializer not serializing the foreign key object

I know that this question has been asked before, but I've tried so many different solutions and just cannot seem to get it to work. All I am attempting to do is display one object within another on an api call. In this simple example, lets say that I have an artist object and a track object. When I serialize the track object, I would like for the artist object that it refers to using a foreign key to be displayed.
Here is my models.py:
from django.db import models
class Artist(models.Model):
artist_name = models.CharField(max_length=100)
class Track(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE, verbose_name='Artist' )
track_name = models.CharField(max_length=100)
and my serializers.py
from rest_framework import serializers
from . import models
class ArtistSerializer(serializers.ModelSerializer):
class Meta:
model = models.Artist
fields = '__all__'
class TrackSerializer(serializers.ModelSerializer):
artist = ArtistSerializer(read_only=True)
class Meta:
model = models.Track
fields = ('id', 'track_name', 'artist')
If anyone could help, it would be greatly appreciated!
Thanks

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)

Categories

Resources