Django: Change field label in admin doesn't work - django

Unfortunately, I'm still using django 1.4 and the verbose_name doesn't work for foreign keys.
It is there a way to change the label of a foreign key. For now, it is not working:
class ProductVariant(models.Model):
product = models.ForeignKey(TestProduct, verbose_name='test product', on_delete=models.PROTECT)
ProductVariant
class ProductVariantForm(forms.ModelForm):
product = forms.ModelChoiceField(queryset=TestProduct.objects.order_by("product__article_code"))
test_software = forms.ModelChoiceField(queryset=TestSoftware.objects.order_by("name"))
class Meta:
model = ProductVariant
class ProductVariantAdmin(admin.ModelAdmin):
fields=["product", "test_software", "test_variables", "name", "description"]
list_display = ("name", "product_name", "test_software_name", "test_variables", "description")
search_fields = ["name"]
form = ProductVariantForm
I hope you can help me.
Thanks in advance!

verbose_name should work with Django 1.4 according to the 1.4 docs.
I think because you're overriding the field in the form it's not using the verbose name for the label. What you could do is set the label on the ModelChoiceField.
class ProductVariantForm(forms.ModelForm):
product = forms.ModelChoiceField(label="Test Product", queryset=TestProduct.objects.order_by("product__article_code"))
test_software = forms.ModelChoiceField(queryset=TestSoftware.objects.order_by("name"))
class Meta:
model = ProductVariant
I'm not quite sure how to use the model's verbose name on the field though, so you might have to define it twice.

Related

Django UpdateView CheckboxSelectMultiple - How do I load an object's ManyToMany field in CheckboxSelectMultiple?

My UpdateView draws from a ModelForm where the sport_prefs field loads as CheckboxSelectMultiple. The form loads correctly and submits data to the MemberRecord model successfully.
My issue is in the UpdateView even though the sport_prefs field shows up as checkboxes, it does not load the current object sport_prefs field's data. The checkboxes load as blank and while I can select options and it will update and save correctly, I cannot load the sport_prefs data from when it was first created or last updated.
models.py
class SportOptions(models.Model):
sport_name = models.CharField(max_length=200)
class MemberRecord(models.Model):
name = models.ForeignKey(ContactInfo, on_delete=models.PROTECT)
age = models.IntegerField()
join_date = models.DateField(default=timezone.now)
sport_prefs = models.ManyToManyField(SportOptions)
notes = models.TextField(blank=True)
author = models.ForeignKey(User, on_delete=models.PROTECT)
forms.py
class createForm(ModelForm):
sport_preference = forms.ModelMultipleChoiceField(
queryset=SportOptions.objects.filter(),
widget=forms.CheckboxSelectMultiple
)
class Meta:
model = MemberRecord
fields = [
'name',
'age',
'join_date',
'sport_preference',
'notes'
]
My guess is I created a new CheckboxSelectMultiple field and I load the correct options because I draw from the SportOptions model but I do not draw from the specific object's sport_prefs. This shows true when I change the ModelForm 'sport_preference' back to 'sport_prefs' as it loads the data correctly but it does not load as CheckBoxSelectMultiple. I am guessing I need to pass the object id through the query set filter in sport_preference if I want to load the data as checkboxes? If so, how do I do that?
The name of the field is sport_prefs, so you should use that field name. If you want to use a different label, you can specify a label=… parameter [Django-doc]:
class createForm(ModelForm):
sport_prefs = forms.ModelMultipleChoiceField(
label='Sport preferences',
queryset=SportOptions.objects.all(),
widget=forms.CheckboxSelectMultiple()
)
class Meta:
model = MemberRecord
fields = [
'name',
'age',
'join_date',
'sport_prefs',
'notes'
]

Django admin page combobox, possible?

I have a simple model in django with a field using choices. As it is now, I am forced to use one of the available choices, how can I be able to use those choices and also be able to enter text manually?
WHERE_CHOICES = (
('CHL', 'Center HL'),
('CHD', 'Center HD')
)
class Event(models.Model):
ev_start = models.DateTimeField()
ev_end = models.DateTimeField()
where = models.CharField(max_length=3, default='CHL', choices=WHERE_CHOICES)
Thanks
You can override the admin form field widget with a datalist tag.
It would look like that (using the floppyforms library):
class EventAdminForm(ModelForm):
class Meta:
model = Event
fields = "__all__"
widgets = {
'where': floppyforms.widgets.Input(datalist=[v[0] for v in Event.WHERE_CHOICES])
}
class EventAdmin(admin.ModelAdmin):
form = EventAdminForm
admin.site.register(Event, EventAdmin)

Specifying a FilterSet for Django-rest-framework

The tutorial said:
class ProductFilter(django_filters.FilterSet):
min_price = django_filters.NumberFilter(lookup_type='gte')
max_price = django_filters.NumberFilter(lookup_type='lte')
class Meta:
model = Product
fields = ['category', 'in_stock', 'min_price', 'max_price']
but when I try to do this, I get an error:
FieldError: Cannot resolve keyword u'min_price' into field. Choices are: cantidad, datetime, enlace, id, id_fila, nivel
min_price is not in my models, but I need to create a new parameter. (it is an example)
really I need to filter dates.
See the django-filter documentation.
Since your min_price and max_price filters don't have the same name as the model field they refer too, you need to provide the name argument.
class ProductFilter(django_filters.FilterSet):
min_price = django_filters.NumberFilter(name='price', lookup_type='gte')
max_price = django_filters.NumberFilter(name='price', lookup_type='lte')
class Meta:
model = Product
fields = ['category', 'in_stock', 'min_price', 'max_price']

Access foreign key fields from Admin Tabular Inline

I'm trying to access a field of a foreign key within a Tabular Inline in the Django Admin.
Despite my best efforts I can't seem to get it working. My current code is:
class RankingInline(admin.TabularInline):
model = BestBuy.products.through
fields = ('product', 'account_type', 'rank')
readonly_fields = ('product', 'rank')
ordering = ('rank',)
extra = 0
def account_type(self, obj):
return obj.products.account_type
Which results in:
'RankingInline.fields' refers to field 'account_type' that is missing from the form.
I have also tried using the model__field method, which I used as:
fields = ('product', 'product__account_type', 'rank')
Which results in:
'RankingInline.fields' refers to field 'product__account_type' that is missing from the form.
The models are defined as so:
class Product(BaseModel):
account_type = models.CharField(choices=ACCOUNT_TYPE_OPTIONS, verbose_name='Account Type', max_length=1, default='P')
class Ranking(models.Model):
product = models.ForeignKey(Product)
bestbuy = models.ForeignKey(BestBuy)
rank = models.IntegerField(null=True, blank = True)
class BestBuy(BaseModel):
products = models.ManyToManyField(Product, through='Ranking')
class BaseModel(models.Model):
title = models.CharField(max_length = TODO_LENGTH)
slug = models.CharField(max_length = TODO_LENGTH, help_text = """The slug is a url encoded version of your title and is used to create the web address""")
created_date = models.DateTimeField(auto_now_add = True)
last_updated = models.DateTimeField(auto_now = True)
What am I doing wrong?
I think what you are looking for is nested inlines since you want to expand "Product" as inline within RankingInline. At present Django does not have such feature built in. This question is relevant: Nested inlines in the Django admin?
You can also look at "Working with many-to-many intermediary models" section in Django DOC. That might be useful.
Actually Django will show you a small green '+' button besides the inline product field entry which you can use to create a new product to assign to your current entry for BestBuy. This might be an alternative for you to use.
You simply need to add the method-field to readonly_fields:
readonly_fields = ('product', 'rank', 'account_type')
Your new field account_type should be defined in ModelAdmin (i.e. RankingAdmin) not in TabularInline (i. e. RankingInline). It should be only accessed from TabularInline.

Django Form with no required fields

I want to make a form used to filter searches without any field being required. For example given this code:
models.py:
class Message(models.Model):
happened = models.DateTimeField()
filename = models.CharField(max_length=512, blank=True, null=True)
message = models.TextField(blank=True, null=True)
dest = models.CharField(max_length=512, blank=True, null=True)
fromhost = models.ForeignKey(Hosts, related_name='to hosts', blank=True, null=True)
TYPE_CHOICES = ( (u'Info', u'Info'), (u'Error', u'Error'), (u'File', u'File'), (u'BPS', u'BPS'),)
type = models.CharField(max_length=7, choices=TYPE_CHOICES)
job = models.ForeignKey(Jobs)
views.py:
WHEN_CHOICES = ( (u'', ''), (1, u'Today'), (2, u'Two days'), (3, u'Three Days'), (7, u'Week'),(31, u'Month'),)
class MessageSearch(ModelForm): #Class that makes a form from a model that can be customized by placing info above the class Meta
message = forms.CharField(max_length=25, required=False)
job = forms.CharField(max_length=25, required=False)
happened = forms.CharField(max_length=14, widget=forms.Select(choices=WHEN_CHOICES), required=False)
class Meta:
model = Message
That's the code I have now. As you can see it makes a form based on a model. I redefined message in the form because I'm using an icontains filter so I didn't need a giant text box. I redefined the date mostly because I didn't want to have to mess around with dates (I hate working with dates! Who doesnt?) And I changed the jobs field because otherwise I was getting a drop down list of existing jobs and I really wanted to be able to search by common words. So I was able to mark all of those as not required
The problem is it's marking all my other fields as required because in the model they're not allowed to be blank.
Now in the model they can't be blank. If they're blank then the data is bad and I don't want it in the DB. However the form is only a filter form on a page to display the data. I'm never going to save from that form so I don't care if fields are blank or not. So is there an easy way to make all fields as required=false while still using the class Meta: model = Message format in the form? It's really handy that I can make a form directly from a model.
Also this is my first serious attempt at a django app so if something is absurdly wrong please be kind :)
You can create a custom ModelForm that suit your needs. This custom ModelForm will override the save method and set all fields to be non-required:
from django.forms import ModelForm
class SearchForm(ModelForm):
def __init__(self, *args, **kwargs):
super(SearchForm, self).__init__(*args, **kwargs)
for key, field in self.fields.iteritems():
self.fields[key].required = False
So you could declare your forms by simply calling instead of the ModelForm, e.g.:
class MessageForm(SearchForm):
class Meta:
model = Message
You could also pass empty_permitted=True when you instantiate the form, e.g.,
form = MessageSearch(empty_permitted=True)
that way you can still have normal validation rules for when someone does enter data into the form.
I would give a try to the django-filter module :
http://django-filter.readthedocs.io/en/develop/
fields are not required. these are filters actually. It would look like this :
import django_filters
class MessageSearch(django_filters.FilterSet):
class Meta:
model = Message
fields = ['happened', 'filename', 'message', '...', ]
# django-filter has its own default widgets corresponding to the field
# type of the model, but you can tweak and subclass in a django way :
happened = django_filters.DateFromToRangeFilter()
mandatory, hidden filters can be defined if you want to narrow a list of model depending on something like user rights etc.
also : setup a filter on a 'reverse' relationship (the foreignkey is not in the filtered model : the model is referenced elsewhere in another table), is easy, just name the table where the foreign key of the filtered model field is :
# the 'tags' model has a fk like message = models.ForeignKey(Message...)
tags= django_filters.<some filter>(name='tags')
quick extendable and clean to setup.
please note I didn't wrote this module, I'm just very happy with it :)