In a template for a view I would like to use the name of a field and not just the value.
So for example if I have this:
class Test(models.Model):
name = models.CharField(max_length=2, verbose_name = 'Your name')
age = models.PositiveSmallIntegerField(max_length=3)
I would like to be able to do {{ name.get_field_name_display }} which will result in either the field's name or the verbose name if it is specified; like the way it is done in the admin and forms. Imagine using it like this in the template:
{{name.get_field_name_display}}: {{name}}.
{{age.get_field_name_display}}: {{age}}.
Which would result in, for example:
Your name: John. Age: 16.
where 'Your name' is the field verbose name, 'Age' is the field name and 'John' and 16 are the values.
Could anyone tell me if this is possible and how it is done?
Not easily.
Related
I have a model than has a lot of models.BooleanField declarations.
class a_lot_of_booleans(model.Models):
old_or_new = models.BooleanField(default=False,verbose_name="is it an old or a new item")
product_for_teens = models.BooleanField(default=False,verbose_name="is this product for teens")
in_original_package = models.BooleanField(default=False,verbose_name="is this product in original package?")
Which then is used in some other classes like:
class product_for_sale(a_lot_of_booleans):
U_Id = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
product_name=models.CharField(max_length=50)
class product_for_buying(a_lot_of_booleans):
U_Id = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
product_name=models.CharField(max_length=50)
The class a_lot_of_booleans might change over time. Some booleans might get added some might get removed. What I need is to display a list of several entries, of the verbose_name, of only the true fields on one of the classes that inherit the a_lot_of_booleans class and the value of product_name, belonging to specific user.
What I"m trying in the views.py is the following:
def view_rfps(request):
list=product_for_sale.objects.all().filter(U_Id=request.user)
for item in list:
values=item._meta.fields
for value in values:
res=item.objects.filter(**{value:'True'}) ##<< lines that fail
print(res)
the above code fails on res=item.objects.filter(**{value:'True'}) on "Manager isn't accessible via search_for_constructor_rfp instances"
The idea later to pass on the res variable to view, however I cannot pass this point.
I have several items in list and for every list several boolean fields, that I"m not sure what they names gonna be in a future, so I cannot just use product_for_sale. in template later.
Any suggestion how to display the verbose name of unknown boolean field name ?
edit
Found a way:
def view_rfps(request):
list=product_for_sale.objects.all().filter(U_Id=request.user)
for item in list:
values=item._meta.fields
for value in values:
temp=getattr(item,value.name)
if temp:
print(value.verbose_name)
But if someone knows more efficient way, I"d love to hear
This is what worked for me:
def view_rfps(request):
list=product_for_sale.objects.all().filter(U_Id=request.user)
for item in list:
values=item._meta.fields
for value in values:
temp=getattr(item,value.name)
if temp:
print(value.verbose_name)
Good day SO. I am trying to use the get_FOO_display on template but my data is not displaying. Also, I have read other SO answers and I believe that I followed them to a T but not working. Please try to correct me what I do wrong.
How I declared:
Models:
GENDER_CHOICES = (
(1, '男性'),
(2, '女性'),
)
gender = models.PositiveSmallIntegerField(choices=GENDER_CHOICES, default=0, null=False)
forms:
...
self.fields['gender'].widget.attrs.update({'class': 'form-control'})
view:
account = AccountViewForm(initial = {"gender" : account.gender})
template:
{{account.get_gender_display}}
If I only use {{account.gender}}, it becomes a select tag with the correct data. I want to display this as a TEXT tag.
Note. I also cant do <input type="text" value="{{account.gender}}" id="id_gender"> manually since this messes up the template.
It's because you're passing the .gender property, you need the whole model instance that contains the .gender attribute (Account model?)
the .get_FOO_display exists on the model as whole, not the field.
pass the account object in the context and use account_obj.get_foo_display()
For simplicity sake, with models like the following:
class Plan(models.Model)
name = models.CharField(max_length=255, verbose_name="Phone Plan Name")
monthly_charge = models.FloatField()
class Company(models.Model):
name = models.CharField(max_length=255, verbose_name="Company Full Name")
phone_plan = models.ForeignKey(Plan)
class Client(models.Model):
name = models.CharField(max_length=255, verbose_name="Client Full Name")
company = models.ForeignKey(Company)
Given a string, I want to know if there is an easy way to retrieve the verbose name of a model attribute even if that string traverses through foreign keys.
I know that I can get the verbose name of a Client attribute by
Client._meta.get_field("name").verbose_name
and this would result in "Client Full Name".
But what if I had the string "company__phone_plan__name", I cannot simply use
Client._meta.get_field("company__phone_plan__name").verbose_name
to arrive at "Phone Plan Name" as it yields an error.
These strings will be dynamic, so I am wondering what is the easiest way to arrive at the proper verbose name of an attribute, even if it traverses models?
This particular case is using Django 1.11
This is not so good answer but if you need what you want you can use this function:
def get_verbose_name(model, string):
fields = string.split('__')
for field_name in fields[:-1]:
field = model._meta.get_field(field_name)
if field.many_to_one:
model = field.foreign_related_fields[0].model
elif field.many_to_many or field.one_to_one or field.one_to_many:
model = field.related_model
else:
raise ValueError('incorrect string')
return model._meta.get_field(fields[-1]).verbose_name
This function gets model name and string and return verbose name
You can use it like so:
get_verbose_name(Client, 'company__phone_plan__name')
If you are working with instances of the models, then you could try this:
c = Client.objects.first()
# c._meta.get_field('company').verbose_name
# c.company._meta.get_field('phone_plan').verbose_name
c.company.phone_plan._meta.get_field('name').verbose_name
If you are working with classes only, then its a but more complex:
field_company = Client._meta.get_field('company')
field_phone_plan = field_company.rel.to._meta.get_field('phone_plan')
field_name = field_phone_plan.rel.to._meta.get_field('name')
field_name.verbose_name
# or one long line
s = Client._meta.get_field('company') \
.rel.to._meta.get_field('phone_plan') \
.rel.to._meta.get_field('name') \
.verbose_name
EDIT:
User #AndreyBerenda points out that the second option does not work for him in Django 2.1; I tested only in 1.11, which was specified in the question.
I need to make a selector with genders (male and female) with the respectives counts of each type.
For example, if I have 4 males and 8 females in my DB, I need a select tags with options
"Select gender"
"Male (4)"
"Female (8)"
In my Form class I have
gender = forms.ModelChoiceField(
queryset=Gender.objects.all().annotate(counter=Count('user')),
required=False,
label="Gender"
)
And I don't know how to render this select element. If I use {{ form.gender }} I can't even display the options. I get Error binding parameter 0 - probably unsupported type. It could be an SQLite issue? I will use PostgreSQL as my DB anyway.
Any suggestions?
EDIT: I need something like this, with almost 10 form fields and a variable number of options in each case
I would do it this way. I tried this and it works fine. Modify it for your needs and it should work fine as well. I am just modifying the widget for gender field.
class testform(forms.ModelForm):
class Meta:
model = names
fields = ['name', 'gender']
male = 'male'+str(names.objects.filter(gender='m').count())
female = 'female'+str(names.objects.filter(gender='f').count())
choices = ((male, male),(female,female))
gender = forms.CharField(widget=forms.Select(choices=choices))
You can override label_from_instance method of ModelChoiceField:
class GenderModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return obj.name + ' ({})'.format(obj.counter)
And use this custom field in your form:
gender = GenderModelChoiceField(
queryset=Gender.objects.all().annotate(counter=Count('user')),
required=False,
label="Gender"
)
I have a site which is joomla 2.5 version. I have used chronoform. I have configured chronoform mail with field values like Nombre{Nombre}.But the mail is going in spam and in the body I am getting like below..
Nombre {Nombre}
Apellido {Apellido}
Ciudad {Ciudad}
Telefono {Telefono}
Correo electrónico {Correo electronico}
Mensaje {Mensaje}
I am not getting the values of {Nombre} etc.
You need to make sure that the field name is declared in chronoforms.
If you go into your form and click on the wizard (if you used the wizard) - you'll see your form fields. Click to edit your form field and your options window will appear.
You will see 'Label Text', 'Field Name', 'Field Default Value', etc.
You MUST fill in the field name for each of them in order to get their values into the email. So for example Nombre would be:
Label Text: Nombre:
Field Name: Nombre
Then you could do "Nombre: {Nombre}" in your email template to get the value.