I started using django framework just a few days ago and i desperately need some help with my application.
It consists of client,project,admin,and admin payment classes where the admin_payment holds the ids of the admins and projects among other stuff.
My question is how i can display the "administrator's name" of each "project" in my admin listing of projects? the project class itself does not hold the administrator ids (the Admin_Payment does)
Currently i have the following structure: (striped down)
models.py
class Admin(models.Model):
admin_name = models.CharField(unique = True, blank = False, null = False, max_length = 128, verbose_name = u'admin full name')
def __unicode__(self):
return self.admin_name
class Meta:
ordering = ('id',)
verbose_name = u'Admin Info'
class Project(models.Model):
client = models.ForeignKey(Client, verbose_name = u'Client')
description = models.ForeignKey(Description, verbose_name = u'project description')
admins = models.ManyToManyField(Admin, verbose_name = u'Administrators', through = 'Admin_Payment')
class Admin_Payment(models.Model):
admin = models.ForeignKey(Admin, verbose_name = u'Administrator')
project = models.ForeignKey(Project, verbose_name = u'project')
admin.py (striped down)
class AdminInline(admin.TabularInline):
model = Admin
class ProjectAdmin(admin.ModelAdmin):
radio_fields = {'position': admin.HORIZONTAL, 'solution': admin.HORIZONTAL}
inlines = [AdminInline, ]
list_display = ['client','description','admin_name']
Clients and Descriptions appear correctly in the project listing but the admin names are not
Any help is appreciated
(sorry if i posted anything that doesnt make sense , i am a newbie in python and django)
Displaying the contents of ManyToMany field isn't supported by default by django, because the database will be queried for each row of the results. You can display it yourself by adding a method to your Project-model:
class Project(models.Model):
....
def admin_names(self):
return ', '.join([a.admin_name for a in self.admins.all()])
admin_names.short_description = "Admin Names"
and put admin_names in your list_display fields!
Related
I have two models, which are linked reverse by foreign key from my admin point of view:
class Product(models.Model):
name = models.CharField("name", max_length = 128)
class Store(models.Model):
store_id = models.PositiveIntegerField(unique = True)
product = models.ForeignKey(Product, on_delete = models.CASCADE, null = True, blank = True)
And I have an admin view where I want to display the store_id of each product it is available in list_display.
I ask because I found TabularInline - my apporach:
class StoreInline(admin.TabularInline):
model = Store
readonly_fields = ['store_id', "product"]
#admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ["name",]
inlines = [StoreInline,]
But how would i be able to display the store_id value in list_displays using the Inlines method?
--- workaround (this is only a motviation for my question above), not a solution ---
I worked around by creating a custom method but, I feel like from reading (1, 2, 3) that I have solved it "by hand" and not using a path Django already has. This works:
#admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ["name", "get_stores"]
def get_stores(self, obj):
return [s.store_id for s in Store.objects.filter(product = obj)]
so I am building an app with django django rest and I have some issues with many to many fields in my models,
in the app there are two models that are connected by a many to many field option and version. the problem is that I want to filter my option and get only the option related to a number of version and only those who have (Default True).
here is my models
class Option(models.Model):
Code_Option = models.CharField(max_length=20, primary_key=True)
Nom_Option = models.CharField(max_length=100)
option_Version = models.ManyToManyField(Version,through='Option_Version')
class Option_Version(models.Model):
option = models.ForeignKey(Option, on_delete=models.CASCADE)
version = models.ForeignKey(Version, on_delete=models.CASCADE)
Default = models.BooleanField(default = False)
class Version(models.Model):
Code_Version = models.CharField(max_length=20, primary_key=True)
Nom_Version = models.CharField(max_length=200)
Id_Modele = models.ForeignKey(Modele, on_delete=models.CASCADE, related_name='Version_set')
and here is what I tried to do
class Option_defaut_Version(ListAPIView):
serializer_class = Option_Sereializer
def get_queryset(self):
id_version = self.kwargs['Id_Version']
//id version refers to Code_Version from Version (it's the PK) and I get it from the url ex: option/default/<srt:Id_Version>
return Option.objects.filter(option_Version__version = id_version).filter(option_Version__default = "True")
and here is my sereilasers :
class Option_Sereializer(serializers.ModelSerializer):
class Meta:
model = Option
fields = [
'Code_Option',
'Nom_Option',
'option_Version'
]
class Option_Version_Sereializer(serializers.ModelSerializer):
class Meta:
model = Option_Version
fields = [
'option',
'version',
'Default'
]
class Version_Sereializer(serializers.ModelSerializer):
class Meta:
model = Version
fields = [
'Nom_Version',
'Code_Version'
]
also I tried this:
class option_version_default(ListAPIView):
serializer_class = Option_Version_Sereializer
def get_queryset(self):
return Option_Version.objects.all()
the result was an error:
AttributeError at /option/default/v1
type object 'Option_Version' has no attribute 'objects'
if anyone could help me I would apreciate it
ps: I saw a lot of other questions and answers also the doc from django django rest but it didn't help me
This is my Device that I registered in admin.py:
#admin.register(Device)
class DeviceAdmin(admin.ModelAdmin):
search_fields = ["device_type","serial_number","in_use_by","brand","model","type_number","mac_address"]
list_display = ("device_type","serial_number","in_use_by","brand","model","type_number","mac_address","invoice",)
list_filter = ("device_type","in_use_by","brand",)
This is my Device model in models.py
class Device(models.Model):
device_type = models.ForeignKey(DeviceType,to_field='device_type')
serial_number = models.CharField(max_length=200,unique=True)
in_use_by = models.ForeignKey(User,to_field='username')
brand = models.CharField(max_length=200,default="-", null=False)
model = models.CharField(max_length=200,default="-", null=False)
type_number = models.CharField(max_length=200,blank=True,null=True, default = None)
mac_address = models.CharField(max_length=200,blank=True,null=True, default = None)
invoice = models.BinaryField(blank=True)
This is my form class from forms.py
class ReturnForm(forms.ModelForm):
class Meta:
model = Device
fields = "__all__"
widgets = {"device_type": forms.Select(attrs={"class":"custom-select col-sm-4"})}
exclude = ("serial_number","in_use_by","brand","mac_address","type_number","model","invoice",)
Now, when I view my admin panel, the invoice gets displayed as a column name in the panel. But, when I view an object in more detail by clicking it, the invoice field is not displayed.
What is the problem that has occured?
How can I resolve this issue?
Requesting immediate help.
BinaryField can not be used in a ModelForm, and thus I suspect it also can't be displayed in the admin's change form. You can consult the documentation on BinaryField here: https://docs.djangoproject.com/en/2.0/ref/models/fields/#binaryfield .
Also note the warning about abusing BinaryField to store files in the database.
In our project, i've been making use of the latest version of django-nested-inlines v0.3.7 with django 1.7
I have the following definition in my django admin to display the inlines
class SpecsGroupedContentInline(NestedStackedInline):
model = SpecificationGroupedContent
extra = 1
fk_name = "specification"
fields = ["field_unit"]
class SpecsContentInline(NestedStackedInline):
model = SpecificationListContent
extra = 1
fk_name = "specification"
fields = ["content"]
class SpecsInline(NestedStackedInline):
model = Specification
inlines = [SpecsContentInline, SpecsGroupedContentInline]
extra = 1
fk_name = "product"
class ProductAdmin(NestedModelAdmin):
inlines = [
SpecsInline
]
list_display = ('name', 'sku')
form = ProductAdminForm
When the page loads, the page looks like this
Initial product page load
It's a bit hard to see but the specs section has a title, an inline for Listed Contents and an inline for Grouped Contents. Afterwards, there's an empty Specs section with an empty title, empty Listed Contents, and empty Grouped Contents.
When I press the "Add another Specification" button at the bottom of the Specification inline to add a new row, the result of the new entry looks like this
New Specification entry image
As you can see, the Grouped Content field "Field Unit" is missing. I'm not sure if my setup is incorrect, but i found this stack overflow entry with a similar setup to mine
Django nested inlines not working?
It is for a different error though but we have a similar inline setup so i was thinking this setup is ok for django-nested-inlines.
Also, I'm sure if it's related but is django-nested-inlines affected if a nested inline model is a foreign key of another model? The SpecificationsGroupedContent model is a foreign key of another model unlike the SpecificationsListContent. I did a quick test where the SpecsInline inlines contained either SpecsGroupedContentInline only or SpecsContentInline only. It was working perfectly when using only SpecsContentInline but the error occurs when using SpecsGroupedContentInline.
For reference, here are the models I'm using with the related model for SpecsGroupedContent
class Product(AuthorStampedModel):
name = models.CharField(max_length=100)
sku = models.CharField(unique=True, max_length=100, verbose_name='SKU')
summary = models.TextField(blank=True, default="")
def __unicode__(self):
return self.return_product_details()
def return_product_details(self):
return '%s: %s' % (self.sku, self.name)
class Specification(models.Model):
product = models.ForeignKey('Product', related_name='specs')
title = models.CharField(max_length=100)
def __unicode__(self):
return self.return_spec_string()
def return_spec_string(self):
return '%s: %s' % (self.product.return_product_details(), self.title)
class SpecificationListContent(models.Model):
specification = models.ForeignKey('Specification', related_name='list_content')
content = models.CharField(max_length=255)
class Meta:
verbose_name_plural = 'Specification Listed Contents'
def __unicode__(self):
return self.specification.return_spec_string()
class SpecificationGroupedContent(models.Model):
specification = models.ForeignKey('Specification', related_name='group_content')
field_unit = models.CharField(max_length=255)
class Meta:
verbose_name_plural = 'Specification Grouped Contents'
def __unicode__(self):
return self.specification.return_spec_string()
class SpecificationGroupedContentValue(models.Model):
specification_grouped_content = models.ForeignKey(
'SpecificationGroupedContent',
related_name='group_content_value'
)
value = models.CharField(max_length=255)
class Meta:
verbose_name_plural = 'Specification Grouped Content Values'
def __unicode__(self):
return self.specification_grouped_content.specification.return_spec_string()
Thanks
Problem Statement:
I am using Django admin to manage many tables, some of which have many-to-many relationships. I am unable to save new records in tables (models) that have manytomany fields defined. I am able to render the add form just fine. The problem is only upon trying to save the record. I do not have the same problem when updating an existing record.
Using the models below, I receive the following error: 'Bout' instance needs to have a primary key value before a many-to-many relationship can be used.
The Bout model has a many-to-many relationship with the Equipment model. The BoutEquipment model is the intermediate model.
I've researched this problem high and low on StackOverflow and via Google, but am thus far unable to find a solution.
Disclosure: I'm new to Django and new-ish to Python. I'm hopeful that there's a relatively simple solution to this problem.
Thanks in advance.
models.py
class Bout(models.Model):
boutid = models.AutoField(db_column=u'BoutID', primary_key=True)
sessionid = models.ForeignKey(Session, db_column=u'SessionID', verbose_name=u'Session')
activitytypeid = models.ForeignKey(Activitytype, db_column=u'ActivityTypeID', verbose_name=u'Activity Type')
locationid = models.ForeignKey(Location, db_column=u'LocationID',verbose_name=u'Location')
equipment = models.ManyToManyField(Equipment, verbose_name=u'Related Equipment', related_name=u'Bout_Equipment', blank=True, null=True) #through = 'BoutEquipment'
intensitymetrics = models.ManyToManyField(Intensitymetric, verbose_name=u'Related Intensity Metrics', related_name=u'Bout_IntensityMetrics', blank=True, null=True) #through = 'BoutIntensitymetric'
def __unicode__(self):
return u'%s %s' % (self.sessionid, self.activitytypeid)
class Meta:
db_table = u'app_bout'
verbose_name = u'Bout'
verbose_name_plural = u'Bouts'
class Equipment(models.Model):
equipmentid = models.AutoField(db_column=u'EquipmentID', primary_key=True)
name = models.CharField("Name", max_length=100, db_column=u'Name')
equipmenttypeid = models.ForeignKey(Equipmenttype, db_column=u'EquipmentTypeID', verbose_name = u'Equipment Type')
def __unicode__(self):
return self.name
class Meta:
db_table = u'app_equipment'
verbose_name = u'Equipment'
verbose_name_plural = u'Equipment'
class BoutEquipment(models.Model):
id = models.AutoField(db_column=u'id', primary_key=True)
boutid = models.ForeignKey(Bout, db_column=u'Bout_ID')
equipmentid = models.ForeignKey(Equipment, db_column=u'Equipment_ID')
def __unicode__(self):
return self.name
class Meta:
db_table = u'app_bout_equipments'
admin.py
class EquipmentAdmin(admin.ModelAdmin):
form = EquipmentForm
inlines = [EquipmentShoeInline, EquipmentLogInline]
list_display = ('name','equipmenttypeid','manufacturer','retired','retiredby','retiredon','notes')
fields = (
'name',
('equipmenttypeid','manufacturer'),
('retired','retiredby','retiredon'),
'notes'
)
class BoutAdmin(admin.ModelAdmin):
form = BoutForm
filter_horizontal = ('equipment','intensitymetrics',)
list_display = ('sessionid','activitytypeid','locationid','sequence','activehand','baddata')
inlines = [BoutDeviceInline,]
fields = (
('sessionid','locationid','activitytypeid'),
'videofilelocation',
'sequence',
'activehand',
'notes',
'baddata',
('equipment','intensitymetrics')
)
A manytomany field in django is a join table between the two models you want to connect to each other.
This happens on SQL level, so both models have to exist in the database.
bout = Bout()
...
equipment = Equipment()
...
bout.equipment.add(equipment)
#fails because bout and equipment are not saved
bout.save()
bout.equipment.add(equipment)
#fails because equipment is not saved
equipment.save()
bout.equipment.add(equipment)
#yay :)