I have made a form that contains a field like:
sex = forms.ChoiceField(choices= SEX)
Where:
SEX = (
('F','Female'),
('M','Male'),
('U','Unsure'),
)
Now I'm wondering how best the sex field should be defined the model? I know that it can be done like:
class UserProfile(models.Model):
user = models.ForeignKey('User')
sex = models.CharField(max_length=10)
But isn't there a better option than CharField?
You've set your choices up as strings so it should be a CharField(max_length=1, choices=SEX) in the model. You could then use a ModelForm instead of repeating all the logic in a separate form. For example:
# models.py
class MyModel(models.Model):
SEX_CHOICES = (
('F', 'Female',),
('M', 'Male',),
('U', 'Unsure',),
)
sex = models.CharField(
max_length=1,
choices=SEX_CHOICES,
)
# forms.py
class MyForm(forms.MyForm):
class Meta:
model = MyModel
fields = ['sex',]
Since Django 4.04
Now there is a more proper way to do it. Check it out.
Basically, you'll need to create a enum class like
class SexOptions(models.TextChoices):
FEMALE = 'F', 'Female'
MALE = 'M', 'Male'
UNSURE = 'U', 'Unsure'
class UserProfile(models.Model):
user = models.ForeignKey('User')
sex = models.CharField(max_length=1, choices=SexOptions.choices)
Old Answer
class UserProfile(models.Model):
SEX_FEMALE = 'F'
SEX_MALE = 'M'
SEX_UNSURE = 'U'
SEX_OPTIONS = (
(SEX_FEMALE, 'Female'),
(SEX_MALE, 'Male'),
(SEX_UNSURE, 'Unsure')
)
user = models.ForeignKey('User')
sex = models.CharField(max_length=1, choices=SEX_OPTIONS)
I do prefer this way, it's easier to reference the options inside your code.
UserProfile.objects.filter(sex__exact=UserProfile.SEX_UNSURE)
Related
In The Models.py file (I have this codebase)
class Person(models.Model):
sex_choices = (
('Male', 'Male'),
('Female', 'Female')
)
martial_choices = (
('Single', 'Single'),
('Married', 'Married'),
('Divorce', 'Divorce'),
('Widowed', 'Widowed')
)
name = models.CharField(max_length=200)
sex = models.CharField(choices=sex_choices, max_length=50)
martial_status = models.CharField(choices=martial_choices, max_length=50)
age = models.IntegerField()
def __str__(self):
return self.name
class DetailsOfEducationQualification(models.Model):
type_choice = (
("Government", "Government"),
("Private", "Private"),
("Anganwadi Center", "Anganwadi Center"),
)
education_proximity_choice = (
("0-5", '0-5km'),
('5-10', '5-10km'),
('10+', 'Above 10km'),
('Outside the state', 'Outside the state'),
)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
course_class = models.CharField(max_length=50, blank=True)
type_of_education_sector = models.CharField(choices=type_choice, max_length=50, blank=True)
education_facility_proximity = models.CharField(choices=education_proximity_choice, max_length=50, blank=True)
In The Admin.py file (I have this)
from .models import (
Person, DetailsOfEducationQualification
)
class DetailsOfEducationQualificationInline(admin.TabularInline):
model = DetailsOfEducationQualification
extra = 0
class PersonAdmin(admin.ModelAdmin):
fieldsets = [
(
'Personal Information', {
'fields':[
'name', 'sex', 'age', 'martial_status'
]
}
),
]
inlines = [
DetailsOfEducationQualificationInline
]
In query shell, I want to get the person 'course_class' since the DetailsOfEducationQualification model is related to Person:
like in he query:
person = Person.objects.get(id=1)
person.course_class
this code gets an error, saying person does not have the attribute...
How do I access the DetailsOfEducationQualification date from the Person model?
course_class is an attribute of DetailsOfEducationQualification class, and not an attribute of Person class,
so you won't be able to access it from a person object.
detail = DetailsOfEducationQualification.objects.get(id=1)
detail.course_class
the above code will return the course_class of DetailsOfEducationQualification with id 1.
if you want to access course_class from a Person object,
then you can use
person = Person.objects.get(id=1)
person.detailsofeducationqualification_set.first().course_class
person.detailsofeducationqualification_set is the Queryset of all DetailsOfEducationQualification objects that has person with id 1 as foreign key.
and, person.detailsofeducationqualification_set.first() will be the first element of the queryset.
hope it helps.
I have this model:
class Rank(models.Model):
RANK_TYPE_CHOICES = (
('O', 'Officer'),
('E', 'Enlisted'),
('V', 'Civilian'),
('C', 'Cadet'),
)
ShortName = models.CharField(max_length=50)
LongName = models.CharField(max_length=500)
Type = models.CharField(max_length=1, choices=RANK_TYPE_CHOICES, default='O')
Genre = models.ForeignKey(Genre, on_delete=models.DO_NOTHING)
Career = models.ForeignKey(Career, on_delete=models.DO_NOTHING)
image = models.ForeignKey(Photos, on_delete=models.DO_NOTHING)
when I perform this ORM action:
models.Rank.objects.values('Type').annotate(total=Count('Type')).order_by()
I get this response
<QuerySet [{'Type': 'O', 'total': 1}]>
Exactly as I want.
However, as you can see, it gives me the short type. How do I make it show the long name instead of the type choice short name?
Thanks.
You will need to add the values manually.
rank_dict = dict(RANK_TYPE_CHOICES)
for obj in my_ranks:
obj['full_type'] = rank_dict[obj['Type']]
I have models:
class Acessories(models.Model):
clother = models.ForeignKey(Clother, on_delete=models.CASCADE)
acessories_type = models.ForeignKey(AcessoriesType, on_delete=models.CASCADE)
name = models.CharField(max_length=30, blank=True)
class Clother(models.Model):
MALE = 'MA'
FEMALE = 'FE'
UNISEX = 'UN'
GENDER_CHOICES = ((MALE, 'Male'), (FEMALE, 'Female'), (UNISEX, 'Unisex'))
commodity = models.ForeignKey(Commodity, related_name='commodity', on_delete=models.CASCADE)
color = models.ManyToManyField(Commodity, related_name='color')
material = models.ManyToManyField(Commodity, related_name='material')
gender = models.CharField(max_length=2, choices=GENDER_CHOICES, default=UNISEX)
How can I make it in one Admin screen?
Need to see and edit this as it was one model.
Thanks!
Try this or visit this link for more information
class AccessoryInline(admin.TabularInline):
model = Acessories
#admin.register(Clothes)
class ClothesAdmin(admin.ModelAdmin):
inlines = [
AccessoryInline,
]
On the template, when I call person.health_issue, I am getting '1','2' instead of 'Abdominal pain','Anaphylaxis'. How to display the value ('Abdominal pain','Anaphylaxis') instead of the code(1 or2 etc).
I tried with this also {{ person.get_health_issue_display }} in template,it is not displayed anything.
forms.py
HEALTH_USSUES = (
('1', 'Abdominal pain'), ('2', 'Anaphylaxis'), ('3', 'Asthma'),
('4', 'Bruising'), ('5', 'Chest pains'), ('6', 'Coughs or Colds')
)
class PersonActionsForm(forms.ModelForm):
action = forms.MultipleChoiceField(widget=forms.Select(), choices=HEALTH_USSUES, required=False)
models.py
class ReportPerson(models.Model):
report = models.ForeignKey(Report)
name = models.CharField('Name', max_length=100)
first_aid = models.BooleanField('First aid', default=False)
health_issue = models.IntegerField(default=0)
views.py
def report_template(request):
""""""
person = ReportPerson.objects.get(pk=person_id)
""""""
return render(request, 'event/print.html',
{
'person':person
})
can any one tell me how to do this.
Thanks
As you don't have any choices set in model field health_issue you need to write the get_health_issue_display method by your self i will name it as health_issue_display so that default get_FOO_display method not gets overridden:
HEALTH_USSUES = (
(1, 'Abdominal pain'), (2, 'Anaphylaxis'), (3, 'Asthma'),
(4, 'Bruising'), (5, 'Chest pains'), (6, 'Coughs or Colds')
)
class ReportPerson(models.Model):
report = models.ForeignKey(Report)
name = models.CharField('Name', max_length=100)
first_aid = models.BooleanField('First aid', default=False)
health_issue = models.IntegerField(default=1)
def health_issue_display(self):
for c in HEALTH_USSUES:
if c[0] == self.health_issue:
return c[1]
Or just add choices in the model field:
health_issue = models.IntegerField(default=1, choices=HEALTH_USSUES)
Now you have get_health_issue_display.
Also make the first value in every choice as integer (1, 'Abdominal pain') rather than string '1'. Just to remove the confusion.
You have default=0 which does not exists in choices. Change it to default=1
I have three classes
Class Company(models.Model):
name = CharField( max_length = 26 , blank = True)
#(...)
class Person(models.Model):
name = CharField( max_length = 26 , blank = True)
function = CharField( max_length = 50 , blank = True)
company = ForeignKey ( Company , related_name = 'persons' )
# All the company table inside the data base is loaded in order to make the query,
# This make a HUGE amount of data and takes too many time...
# (...)
def __unicode__(self):
# caption uses both name and company__name fields but no other fields
return self.name + '(' + self.company.name + ')'
class Contact(models.Model):
person = ForeignKey ( Person )
In order to optimise performances, I would like the latest person field to use
Person.objects.all().only('name', 'company__name')
as queryset. Is it possible?
You can use values method, which return a subclass of QuerySet called ValuesQuerySet.
Person.objects.all().values('name', 'company__name')
For more information Django Doc
Use proxy models :
class Person_short_manager(Manager):
def get_query_set(self):
return super(self, Person_short_manager).get_query_set().only('name','company__name')
class Person_short(Person):
objects = Person_short_manager(Manager)
class Meta:
proxy = True
then replace
person = ForeignKey ( Person )
by
person = ForeignKey ( Person_short )