I have a ManyToMany relationship setup with intermediary objects in Django. Any ideas how I can order the < select >s in the Inlines that show up for the intermediary objects?
You can use fields inside an InlineModelAdmin:
class FooInline(admin.StackedInline):
model = Foo
fields = ('field1', 'field2', 'field3')
I think this could be what you're looking for:
Orderable inlines using drag and drop with jQuery UI
http://djangosnippets.org/snippets/1053/
Have you tried specifying a model for the many-to-many relationship using the through argument? You should be able to customize the admin with a ModelAdmin class then.
class A(models.Model):
pass
class B(models.Model):
m2m = models.ManyToManyField(A, through='C')
class C(models.Model):
a = models.ForeignKey(A)
b = models.ForeignKey(B)
Related
I am creating a multi tenant app and have the following abstract class that all relevant tenant specific models inherit from:
class TenantAwareModel(models.Model):
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
class Meta:
abstract = True
When registering models in the Django admin, I want to keep my code DRY and not have to add 'tenant' to every single search_fields, list_display, list_filter etc so I tried creating a super class to inherit from.
class TenantAwareAdmin(admin.ModelAdmin):
class Meta:
abstract = True
# change_form_template = "admin/professional_enquiry_change_form.html"
search_fields = ('tenant__id', 'tenant__name', 'tenant__domain',)
list_display = ('tenant',)
list_filter = ('tenant',)
And then trying to inherit that in the registration of the other models. E.g.
class UserAdmin(TenantAwareAdmin, admin.ModelAdmin ):
...
This approach matches the way the TenantAwareModel works.
class TenantAwareModel(models.Model):
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
class Meta:
abstract = True
class User(AbstractUser, Uuidable, Timestampable, TenantAwareModel):
...
and it is of course giving me:
django.core.exceptions.ImproperlyConfigured: The model TenantAwareModel is abstract, so it cannot be registered with admin.
Does anybody know the proper way to do this to avoid all the duplicated code?
The Meta class and abstract=True can only be defined in the model definition, not in the ModelAdmin.
The TenantAwareModel is an abstract model that allows you to avoid repeating the common fields in the definition of others models, but you can't register a abstract model in the admin site. The abstract model is not related with any table, its only task is to be a base from which inherit in other models that will represent tables(not abstract models) and which will be able to be registered in the admin site.
To avoid repeat the same fields in search_fields, list_display, etc, you should create a mixin like this:
class TenantAwareAdminMixin:
search_fields = [..., ...]
list_display = [..., ...]
...
and inherit from this
class UserAdmin(TenantAwareAdminMixin, admin.ModelAdmin):
...
But there is a problem... If you override some field defined in the TenantAwareAdminMixin, this will overwrite the value provided by the mixin forcing you to explicitly add the inherited values plus those new values, like this:
class UserAdmin(TenantAwareAdminMixin, admin.ModelAdmin):
list_display = TenantAwareAdminMixin.list_display + ['new_value']
...
It is possible to obtain a similar result by overriding the get_list_display, etc. methods.
class DemoForm(forms.ModelForm):
class Meta:
model=SimpleDemo
fields=['First_name','Last_name']
class PostForm(forms.ModelForm):
class Meta:
model=Post
fields = ['Enter_Message',]
I think the django docs are straight forward for your application.
You declare a foreign key field just the same as every other field.
Suppose ModelA and (ModelB1, ModelB2 but they don't have common ancestor) has manytomany relationships.
Now I have a through model ModelAtoB.
class ModelAToB(Model):
model_a = models.ForeignKey(ModelA)
content_type=models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
model_b = generic.GenericForeignKey('content_type', 'object_id')
I see ManyToManyField being used in the django doc, how can I use it in my case as well?
class ModelA(Model):
pass
class ModelB(Model): # hum.. there's no ModelB which is a common ancestor of ModelB1, ModelB2
model_a_list = models.ManyToManyField(ModelA, through='ModelAtoB')
You cannot use the ManyToManyField in your case however your through model (ModelAToB) is enough to store the relation.
If you want to query all related ModelBs models to a given ModelAs you would do it somehow like this:
related_b = ModelAToB.objects.filter(model_a=a).prefetch_related('model_b')
b_instances = [rel.model_b for rel in related_b]
If you want all related ModelAs to a given ModelB this would be done this way:
from django.contrib.contenttypes.models import ContentType
model_b_ct = ContentType.objects.get_for_model(b)
related_a = ModelAToB.objects.filter(object_id=b.id, content_type=model_b_ct)
a_instance = [rel.model_a for rel in related_a]
Making a model method might be a handy tweak.
class ModelB(Model)::
def model_a_list(self):
return ModelA.objects.filter(
modelatob__content_type__app_label=self._meta.app_label,
modelatob__content_type__model=self._meta.module_name,
modelatob__object_id=self.id
)
This returns a queryset so you still can do things like .count(), .filter() on it.
I have 2 models:
models.py:
class Teacher(models.Model):
user = models.ForeignKey(User)
...
class Record(models.Model):
user = models.ForeignKey(User)
...
and admin.py
class RecordInline(admin.StackedInline):
model = Record
class TeacherAdmin(admin.ModelAdmin):
inlines = [RecordInline]
Basically what I want to do is to display records where users are same (teacher.user == record.user) inline in Teacher's detail in admin. The problem is that Teacher and Record do not have direct relationship, so I'm looking for a way to define this relationship.
How can I achieve this? I amd using Django 1.2.5 in my project
You could override one of the ModelAdmin's methods, eg get_inline_instances
class TeacherAdmin(admin.ModelAdmin):
inlines = [RecordInline]
def get_inline_instances(self, request):
# ...
I want to use raw_id_fields on a ManyToMany relationship in the admin, and I want each related object to show up on its own row (as opposed to a comma-separated list in a single field, which is the default behavior). Following examples spotted in the wild, it seems like I should be able to do this:
# models.py
class Profile(models.Model):
...
follows = models.ManyToManyField(User,related_name='followees')
# admin.py
class FollowersInline(admin.TabularInline):
model = Profile
raw_id_fields = ('follows',)
extra = 1
class ProfileAdmin(admin.ModelAdmin):
search_fields = ('user__first_name','user__last_name','user__username',)
inlines = (FollowersInline,)
admin.site.register(Profile,ProfileAdmin)
But that generates the error:
<class 'bucket.models.Profile'> has no ForeignKey to <class 'bucket.models.Profile'>
I'm not clear what I'm doing wrong here. Thanks for suggestions.
Looks like you are setting the wrong model for your InlineAdmin
as the model for followers you are defining is User and not Profile.
Looking at the docs I'd say you should try:
class FollowersInline(admin.TabularInline):
model = Profile.follows.through
and
class ProfileAdmin(admin.ModelAdmin):
....
exclude = ('follows',)
inlines = (FollowersInline,)
In inline for m2m connection you should use through table and for raw_id_fields setting you should use fields from that through table - inside this table fields can be name different as you expect.
You need goes to sqlite3/psql etc. terminal to see through table schema and use propper field for raw_id_fields.
class FollowersInline(admin.TabularInline):
model = Profile.follows.through
# raw_id_fields = ("follows",) <- wrong
raw_id_fields = ("user",) # <- probably right, because your m2m relation with `User` table and django use name of that table to name field in `through` model