I have a Django project that includes a model class with an optional self-referential ForeignKey field. A partial snippet:
class Site(models.model):
name = models.CharField(max_length=100)
parent_site = models.ForeignKey('self', null=True, blank=True)
I'm using the Django admin site to create new objects. For this class' admin form I'd like to disable the "Add another..." button next to the parent_site field (i.e. when you're creating a new site, you can't open the popup to create another new site as the parent).
I can't remove has_add_permission from the user, as they need it to be in the current add view. I don't mind removing the function from both add and change views, but limiting removal to the add view would be helpful.
I haven't been able to work out how to use the Inline field classes to achieve this, or formfield_for_foreignkey, or a custom ModelForm. Anyone got a solution more elegant than using JavaScript on a customised form template?
no css hacks add to admin class:
max_num=0
or try this in admin.py ( for older django versions):
class MODEL_ADMIN(admin.ModelAdmin):
class Media:
css = {'all': ('css/no-addanother-button.css',)}
Related
I'm developing a Django application in which a lot of models have foreign keys and m2m relationships. This results in many ModelChoiceField being displayed in the Django admin for my models. To make model choice more bearable, I installed the django-select2 app in my project.
I have been trying to implement select2 in the inline forms the admin site displays when editing related objects, but the form doesn't render the ModelSelect2Widget (it renders a simple select; it doesn't even include the select2 library).
What I tried was creating a ModelForm in forms.py overriding the relevant fields widgets, then, using inlineformset_factory, had a variable holding the factory class. Lastly, in admin.py, added my custom inline formset using the formset property of the InlineModelAdmin class.
forms.py
class FichaTecnicaForm(forms.ModelForm):
class Meta:
model = models.FichaTecnica
exclude = ('pelicula',)
widgets = {
'responsable': ModelSelect2Widget,
'cargo': ModelSelect2Widget,
'pais': ModelSelect2Widget
}
FichaTecnicaInline = inlineformset_factory(models.Pelicula, models.FichaTecnica, form=FichaTecnicaForm)
admin.py
class FichaTecnicaInline(admin.TabularInline):
model = models.FichaTecnica
formset = forms.FichaTecnicaInline
extra = 0
# Some other code here
# This is where the inlines are invoked
class PeliculaAdmin(admin.ModelAdmin):
inlines = [
FichaTecnicaInline,
# some other inlines, not relevant...
]
I was expecting that the inline form set would display the select2 widget for the model choice, but instead it displays a standard select widget.
Thank you very much in advance for you help!
I think there is an error in your code where your FichaTecnicaInline class is overwritten by your admin class definition.
Maybe the formset class created by inlineformset_factory, which uses your custom form is being overwritten by defaults from admin.TabularInline. I think the first thing to try is giving them different names.
I am trying to show inactive users as "disabled" in my form's Select widget.
I have a worker who is a django user model.
models.py
class Task(models.Model):
worker = models.ForeignKey(settings.AUTH_USER_MODEL, models.DO_NOTHING, blank=True, null=True,related_name='worker')
It is represented by a ModelForm, using a subclass to display the full name of the user.
forms.py
class UserModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return obj.get_full_name()
class TaskForm(forms.ModelForm):
worker = UserModelChoiceField(queryset=User.objects.filter(is_active=1).order_by('first_name'),widget=forms.Select(attrs={'class':'form-control'}),required=False)
class Meta:
model = Task
fields = ['worker']
Currently, the filter is_active=1 means that inactive users simply don't show in the list and where they've already been selected it appears as "---".
My ideal would be they appear but are greyed out so they are presented but can't be selected.
From reviewing https://djangosnippets.org/snippets/2453/
Which I found in
"Disabled" option for choiceField - Django
I was able to conclude that the subclass of the select should work. However I can't tell how to get between the queryset and the widget in order to achieve the expected result. Reading suggests the render method on the widget might be the way but I couldn't find examples of how to pass the information or exactly where create_option is invoked.
How to implement Dashboard in django admin?
If I have following Model in django. Is there a way, instead of regular Models list,I can have a search box in admin page to search for student using his name and display his particular details...
class MStudent(models.Model):
enroll_no = models.IntegerField()
Name = models.CharField(max_length=200)
photo = models.ImageField(upload_to="static",blank = True)
def __str__(self):
return self.FName+" "+ self.MName+" "+ self.LName
class MStud_Address_ph_no_email(models.Model):
enroll_no = models.ForeignKey(MStudent)
Address = models.CharField(max_length=200)
Personal_mobile= models.IntegerField()
Fathers_mobile = models.IntegerField()
def __str__(self):
return str(self.enroll_no)
From the Django admin documentation:
If you wish to change the index, login or logout templates, you are better off creating your own AdminSite instance (see below), and changing the AdminSite.index_template , AdminSite.login_template or AdminSite.logout_template properties.
So you should create your own AdminSite and set its index_template attribute to a template of yours that implements the Dashboard you want.
To provide a search and a search results view, see adding views to admin sites.
I think you should read the django docs about admin
And in your case if you want to customize the admin look and feel or adding extra fucntionality, you need override the required admin templates like admin/index.html by creating an admin folder in your template directory
Q.Is there a way, instead of regular Models list, I can have a search box in admin page to search for student using his name and display his particular details?
1) Yes Instead of displaying regular Models list I can directly redirect to model Mstudent.using following code
urls.py
from django.http import HttpResponseRedirect
url(r'^admin/$',lambda x:HttpResponseRedirect('/admin/yourapp/yourmodel'))
2) To search for student using his name and display his particular details:
Make MStud_Address_ph_no_email as inline to MStudent in admin.py.
So all in all whenever a user logged in to django admin, He will directly see list of all students and by selecting a particular student he can see all his details.
:)
I'm new to Django so this might be a simple question. I'm trying to build a portfolio site using Django. I'd like to have a homepage, portfolio page, portfolio detail pages, and contact page. There will be about 20 portfolio detail pages - Project A, Project B, Project C. Each project (portfolio detail page) has multiple areas where I can input text that is populated through the Django admin. How do I create custom fields in the admin for each Portfolio Detail page (headline, project name, url, description) and display them in the page template?
I'm confused as do I use the pages section in the Django admin and add custom fields for each page or do I create a custom app with these custom fields? Then let's say Project B needs an extra field for awards. How do I add that custom field for just the Project B page in the Django admin?
There is no reason why you can't add any number of fields to your project by just linking them with foreign keys.
project/models.py
from django.db import models
class Project(models.model):
name = models.CharField(max_length=100)
class ProjectField(models.model):
project = models.ForeignKey(Project)
fieldname = models.CharField(max_length=50)
value = models.TextField(max_length=2000)
With what you are describing, it sounds like you would like to edit the ProjectField values in the Project admin page. The way that the admin page handles that normally is with inlines.
As an example for the models above:
projects/admin.py
from projects import models
from django.contrib import admin
class ProjectFieldInline(admin.StackedInline):
model = models.ProjectField
extra = 0
class ProjectAdmin(admin.ModelAdmin):
inlines = [ProjectFieldInline]
admin.site.register(models.Project, ProjectAdmin)
I can't say one hundred percent that this will work for what you are asking, but I recomend giving the app above a try and seeing how close it is to what you want.
So I've set up my django site with the following admin.py:
import models
from django.contrib import admin
admin.site.register(models.Comment)
which uses this models.py:
from django.db import models
class Comment(models.Model):
text = models.CharField(max_length=400)
name = models.CharField(max_length=100)
date = models.DateTimeField(auto_now = True)
article = models.CharField(max_length=100)
However, when I go to the admin page, it shows the following:
Which generally is not very helpful. Clicking on each link gives me a page with that object's data, but I would like to be able to see the information for each object in this view. I've been looking at the ModelAdmin class at:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/
but have not managed to wrap my head around it. Is it a separate model class that needs to be kept in sync with my "actual" model? Is it just an interface through which my Admin site accesses the actual model? Does it do what I want (allowing useful data to be shown in the admin interface) or does it do something else?
I'm thinking that the Django Admin page should be able to replace PHPMyAdmin for doing simple tasks, like browsing the DB and manually modifying individual objects. Is that the case?
The admin turns your object into a string so just put a def __str__ or def __unicode__
(As #Mandax has reminded me the docs recommend to define __unicode__ only.)
def __unicode__(self);
return u"%s (%s): %s" % (self.article, self.date, self.name)
Just as it says in the documentation, your model's ModelAdmin describes how the admin section will represent your model. It does need to be somewhat in sync with the actual model, it doesn't make sense for you to display fields that aren't present on your model, etc. You seem interested in the changelist view, which has numerous customization options (all described in the documentation, and in the tutorial). A simple start might be:
from django.contrib import admin
class CommentAdmin(admin.ModelAdmin):
# define which columns displayed in changelist
list_display = ('text', 'name', 'date', 'article')
# add filtering by date
list_filter = ('date',)
# add search field
search_fields = ['text', 'article']
admin.site.register(Comment, CommentAdmin)
There are a lot of options for customization, as always refer to the docs! Finally, you could certainly use it in lieu of PHPMyAdmin, it's very easy to setup admin for browsing, modifying object, etc, how much use you get out of it is up to you.