django admin - custom fields radio - admin.HORIZONTAL not working - django

I have this custom field image_choice in django admin as a radio select.
IMG_CHOICES = (
('embed', _('Embed code')),
('file', _('Upload image')),
('link', _('Image Link'))
)
class BlogArticleForm(forms.ModelForm):
class Media:
js = ('js/myjs.js')
image_choice = forms.ChoiceField(choices=IMG_CHOICES, widget=forms.RadioSelect)
class BlogArticleAdmin(admin.ModelAdmin):
form = BlogArticleForm
fields = ['title', 'description', 'image_choice', 'image_embed', 'image_file', 'image_link']
admin.site.register(models.BlogArticle, BlogArticleAdmin)
I cannot get these radio buttons line up horizontally.
I tried:
radio_fields = {'image_choice': admin.HORIZONTAL}
and
radio_fields = {form.image_choice: admin.HORIZONTAL}
but I keep getting this error:
type object "BlogArticleForm" has no attribute 'image_choice'
how can I achieve this?
this is how it looks like right now:

Take a look at this line.
So I guess it should look something like this:
from django.contrib.admin.options import get_ul_class
class BlogArticleForm(forms.ModelForm):
image_choice = forms.ChoiceField(
choices=IMG_CHOICES,
widget=widgets.AdminRadioSelect(
attrs={'class': get_ul_class(admin.HORIZONTAL)}
))
UPD: I'm stupid :(
It says: if 'widget' not in kwargs: bla-bla-bla adds widget. So this should work with no widget:
image_choice = forms.ChoiceField(choices=IMG_CHOICES)
# And set
radio_fields = {'image_choice': admin.HORIZONTAL}

Related

Make a form that pulls choices from table in DB and then allows user to change to different foreign keys

So I have a user model with the following columns:
username = models.CharField(db_column='Username',max_length=32,unique=True)
email = models.CharField(db_column='Email',max_length=255)
password = models.CharField(db_column='Password',max_length=128)
prosthodontist = models.ForeignKey('Prosthodontist',on_delete=models.SET_NULL,null=True)
I'm trying to make a dropdown that allows the user to change their Prosthodontist value through django forms. It can't be a static list cause it has to always have every available Prosthodontist as they get added.
Just for show this is what I have so far along the lines of the form:
class ChangeProsthodontistForm(forms.ModelForm):
class Meta:
model = User
fields = ('prosthodontist',)
prosthodontist = forms.ChoiceField(
label = "Prosthodontist",
widget = forms.Select(
attrs={
'id':'prosthodontist',
},
),
choices=()
)
Please help me with this cause I'm really confused I feel like I could be able to iterate through the entries with a for loop but I feel like there has to be a better way through Django.
You answer is ModelChoiceField.
prosthodontist = forms.ModelChoiceField(
# ...
queryset = Prosthodontist.objects.all(),
# ...
)

Django: how to add links to my admin site

I have this code in my admin-site,
#admin.register(StudentsEnrollmentRecord)
class StudentsEnrollmentRecord(admin.ModelAdmin):
list_display = ('Student_Users', 'School_Year', 'link',)
ordering = ('Education_Levels',)
list_filter = ('Student_Users',)
Django-adminsite
i just want to add an html_link here and filter what studentenrollmentrecord selected
You can create a function to be used as field:
#admin.register(StudentsEnrollmentRecord)
class StudentsEnrollmentRecord(admin.ModelAdmin):
list_display = ('Student_Users', 'School_Year', 'link_display',)
ordering = ('Education_Levels',)
list_filter = ('Student_Users',)
def link_display(self, obj):
your_url = '' # Define your URL here
return 'link'.format(your_url)
link_display.allow_tags = True
link_display.short_description = 'link'
The function receive the current object as first parameter (obj).
You need to set the allow_tags property to render your link.
You can optionally customize the description (displayed in the header) with short_description.

Django MPTT tree as model filter in admin

I have a model linked to a related model that is a Django MPTT tree model, I would like to be able to filter the first model using the Django MPTT tree in the admin console.
class Tenders(models.Model):
...
sector=models.ForeignKey(Sector, to_field='sectorId', null=True, blank=True,on_delete=models.CASCADE)
...
class Sector(MPTTModel):
name = models.CharField(max_length = 255)
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True,related_name='children')
sectorId = models.IntegerField(default=0,null=True,unique=True)
In the Django admin I would like to set up the filters for the Tenders model such that the Django-MPTT tree is the filter.
I have tried using the following:
class adminTenders(admin.ModelAdmin):
def linkTo(self,obj):
return mark_safe("""<a href='{}' target="_blank" >Tender Link</a>""".format(obj.tenderLink))
linkTo.short_description=''
list_display=(
'title',
'linkTo',
'sector',
'region',
'repository',
'id',
)
list_filter=(
('sector', TreeRelatedFieldListFilter),
)
admin.site.register(Tenders,adminTenders)
However I get the following error when trying to run this and I cant figure it out:
File "py36/lib/python3.6/site-packages/mptt/admin.py", line 314, in field_choices
mptt_level_indent * levels_dict[pk])
KeyError: 0
Any help would be greatly appreciated.
Edit 1: I think I have isolated the issue to the fact that my foreign key in Tenders to Sectors uses a to_field='sectorId instead of the default to link to the pk column. This had to be done for backwards compatibility to an old database scheme that I am stuck with.
So it turns out this is a bug in the django-mptt code for the field_choices function in the TreeRelatedFieldListFilter class.
To fix it I had to subclass and over ride that function to use the to_field that I had defined.
Here is the custom code:
class TreeRelatedForSectors(TreeRelatedFieldListFilter):
# Modified from django-mptt code to fix to_field problem
def field_choices(self, field, request, model_admin):
mptt_level_indent = getattr(model_admin, 'mptt_level_indent', self.mptt_level_indent)
language_bidi = get_language_bidi()
initial_choices = field.get_choices(include_blank=False)
pks = [pk for pk, val in initial_choices]
models = field.related_model._default_manager.filter(sectorId__in=pks)
levels_dict = {model.sectorId: getattr(model, model._mptt_meta.level_attr) for model in models}
choices = []
for pk, val in initial_choices:
padding_style = ' style="padding-%s:%spx"' % (
'right' if language_bidi else 'left',
mptt_level_indent * levels_dict[pk])
choices.append((pk, val, mark_safe(padding_style)))
return choices

Django choicefield choices not displaying

Im using a choicefield and setting 2 values - 'students', 'teachers',
but for some reason when the form displays it only shows 'teachers' and not 'students'.
class SignUpShortForm(SignUpForm):
role = forms.ChoiceField(
choices=[],
widget=forms.Select(attrs={'class':'form-control'}),
label='I am a...',
)
self.fields['role'].choices = [('Teacher', 'Teacher2')]
Please look here You add to your choices only values without keys. Code might look like this:
CHOICES = (
('students', 'Students'),
('teachers', 'Teachers'),
)
class SignUpShortForm(SignUpForm):
role = forms.ChoiceField(
choices=CHOICES,
widget=forms.Select(attrs={'class':'form-control'}),
label='I am a...',
)

Set default value for dropdown in django forms

I am unable to set default value for a dropdown while loading forms.
Here is the code
state = forms.TypedChoiceField(choices = formfields.State)
State = (
('QC_APPROVED','QC_APPROVED'),
('REVERT','REVERT'),
('FIXED','FIXED'),
)
If I want to make the default state as FIXED. I am writing this code
state = forms.TypedChoiceField(choices = formfields.State, default = 'FIXED')
If I execute the above code I am getting the below error.
Exception Value: __init__() got an unexpected keyword argument 'default'
Can some one help on this?
state = forms.TypedChoiceField(choices=formfields.State, initial='FIXED')
As shown in documentation: http://docs.djangoproject.com/en/dev/ref/forms/fields/#initial
I came across this thread while looking for how to set the initial "selected" state of a Django form for a foreign key field, so I just wanted to add that you do this as follows:
models.py:
class Thread(NamedModel):
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
title = models.CharField(max_length=70, blank=False)
forms.py:
class ThreadForm(forms.ModelForm):
class Meta:
model = Thread
fields = ['topic', 'title']
views.py:
def createThread(request, topic_title):
topic = Topic.getTopic(topic_title)
threadForm = ThreadForm(initial={'topic': topic.id})
...
The key is setting initial={'topic': topic.id} which is not well documented in my opinion.
fields take initial values
state = forms.TypedChoiceField(choices=formfields.State, initial='FIXED')
title = forms.CharField(widget=forms.Select(choices=formfields.State) , initial='FIXED')
toppings = forms.ChoiceField(
widget=forms.Select(attrs={'class':"hhhhhhhh"}),
choices = formfields.State,
initial='FIXED'
)
If the other solutions dont work for you,Try this:
It turns out that ModelChoiceField has an attribute called empty_label.With empty _label you can enter a default value for the user to see.
Example: In forms.py
Class CreateForm(forms.ModelForm):
category = forms.ModelChoiceField(empty_label="Choose Category")
Try the number:
state = forms.TypedChoiceField(choices = formfields.State, default = 2 )