See description in django-rest-framework dropdown? - python

How can I see the Subject name in the django-rest-framework dropdown? Now it just says Subject object.
Here are my models:
class Subject(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
owner = models.ForeignKey('auth.User', related_name='subjects')
code = models.CharField(max_length=50)
name = models.CharField(max_length=50)
description = models.CharField(max_length=50)
class Meta:
ordering = ('created',)
def __unicode__(self):
return '%s' % (self.name)
class Grade(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
owner = models.ForeignKey('auth.User', related_name='grades')
code = models.CharField(max_length=3)
requirements = models.CharField(max_length=200)
ranking = models.IntegerField()
subject = models.ForeignKey(Subject, related_name='grades', on_delete=models.CASCADE)
class Meta:
unique_together = ('subject', 'ranking')
ordering = ('ranking',)
def __unicode__(self):
return '%d: %s' % (self.ranking, self.code)

I see you have defined __unicode__ for your model. But perhaps you are using Python 3, in which case for Django models you need to define __str__ not __unicode__
class Subject(models.Model):
...
def __str__(self): # Use this in Python 3
return '%s' % (self.name)
Unrelated, but this is a more succinct return:
def __str__(self):
return self.name

Related

How do I name Django ManyToMany object relations in Django admin?

Is there a way to give the relations their name instead of calling them "object-n" like shown below?
Here is the code for the two models in question:
class jobTag(models.Model):
Tag = models.CharField(max_length=15)
def __str__(self):
return self.Tag
class job(models.Model):
Company_name = models.CharField(max_length=200, null=True, blank= True)
Position = models.CharField(max_length=200, null=False, blank=False)
Type = models.ForeignKey(jobType, default=" ",verbose_name="Type", on_delete=models.SET_DEFAULT)
Industry = models.ForeignKey(jobIndustry, default=" ", verbose_name="Industry", on_delete=models.SET_DEFAULT)
Location = models.ForeignKey(jobLocation, default=" ", verbose_name="Location", on_delete=models.SET_DEFAULT)
Role_description = tinymce_models.HTMLField(default="")
Role_requirements = tinymce_models.HTMLField(default="")
Role_duties = tinymce_models.HTMLField(default="")
Special_benefits = tinymce_models.HTMLField(default="")
Date_posted = models.DateTimeField(auto_now_add=True)
tags = models.ManyToManyField('jobTag', related_name="job-tags+", blank=True)
def time_posted(self):
return humanize.naturaltime(self.Date_posted)
def __str__(self):
return self.Position
class Meta:
verbose_name_plural = "Jobs"
UPDATE:
I tried adding a proxy through-table in models.py but it still doesn't solve the problem. Here:
class jobjobTagProxy(job.tags.through):
class Meta:
proxy = True
def __str__(self):
return self.job.Position + ' // ' + self.tags.Tag
What am I doing wrong?

How can I implement the same widget that Django uses to ManyToMany fields in the admin page?

My models:
class Ingredient(models.Model):
BASE_UNIT_CHOICES = [("g", "Grams"), ("ml", "Mililiters")]
CURRENCY_CHOICES = [("USD", "US Dollars"), ("EUR", "Euro")]
ingredient_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
base_unit = models.CharField(max_length=2, choices=BASE_UNIT_CHOICES)
cost_per_base_unit = models.FloatField()
currency = models.CharField(
max_length=3, choices=CURRENCY_CHOICES, default="EUR")
def __str__(self):
return self.name
class RecipeIngredient(models.Model):
quantity = models.FloatField()
ingredient_id = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
def __str__(self):
return f"{self.quantity} / {self.ingredient_id}"
class Recipe(models.Model):
recipe_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
ingredients = models.ManyToManyField(RecipeIngredient)
date_created = models.DateTimeField('Date Created')
def __str__(self):
return f"{self.name}, {self.ingredients}"
When I use the admin page, it has this + button that allows me to create new ingredient/quantity combinations
like this
But when I try to use it from a form in my code it looks like
this
Here is my form code:
class AddRecipeForm(forms.ModelForm):
class Meta:
model = Recipe
fields = ['name', 'ingredients', 'date_created']
You should write the 'widgets' for each field in you Form that need configuration.
Check the documentation 'Widgets in forms', or even, you can define your own Widgets.

How to return double string in models django

Helo everyone. I have a little problem. I've create a models:
class Cudzoziemiec(models.Model):
imie = models.CharField(max_length=80, verbose_name="Imię", unique=False)
nazwisko = models.CharField(max_length=150, verbose_name="Nazwisko", unique=False)
class Meta:
verbose_name = 'Cudzoziemca'
verbose_name_plural = 'Cudzoziemcy'
def __str__(self):
return self.nazwisko
class Umowa(models.Model):
RODZAJ_UMOWY = (
('UP', 'Umowa o pracę'),
('UZ', 'Umowa zlecenie'),
('UD', 'Umowa o dzieło'),
)
osoba = models.ForeignKey(Cudzoziemiec, on_delete=models.CASCADE, verbose_name="Wybierz cudzoziemca")
umowa_rodzaj = models.CharField(max_length=250,choices=RODZAJ_UMOWY, verbose_name="Rodzaj umowy")
nr_umowy = models.PositiveIntegerField()
umowa_od = models.DateField(auto_now=False, auto_now_add=False, verbose_name="Data rozpoczęcia pracy")
umowa_do = models.DateField(auto_now=False, auto_now_add=False, verbose_name="Data zakończenia pracy")
class Meta:
verbose_name = 'Umowę'
verbose_name_plural = 'Umowy'
def __str__(self):
return self.nr_umowy
In panel admin everything works ok. But how to display "imie"+"nazwisko" in panel admin in case when I want to create a new record in Umowy. Now I have only "nazwisko" if I want to add new record via Umowa class, selected a "osoba" in that class.
EDIT:
When I want to add new record the django return me a error:
__str__ returned non-string (type int)
Not sure if that's what you want, but usually the string representation used in the select input generated by Django forms use the __str__ method:
class Cudzoziemiec(models.Model):
imie = models.CharField(max_length=80, verbose_name="Imię", unique=False)
nazwisko = models.CharField(max_length=150, verbose_name="Nazwisko", unique=False)
class Meta:
verbose_name = 'Cudzoziemca'
verbose_name_plural = 'Cudzoziemcy'
def __str__(self):
return '{} {}'.format(self.imie , self.nazwisko)
Or equivalent result:
def __str__(self):
return '%s %s' % (self.imie , self.nazwisko)
Or if you are using Python 3.6+
def __str__(self):
return f'{self.imie} {self.nazwisko}'
About the "non-string" error, it's because __str__ should return a string object. In your second case, you are returning a self.nr_umowy, which is a PositiveIntegerField.
You have to cast it:
def __str__(self):
return str(self.nr_umowy)

Django: modelchoicefield with multiple modelfields

I would like to request some assistance regarding this matter,
I am fairly new to django and I like it so far.
I have the following model:
class Courses_list(models.Model):
Abbreviation = models.CharField(max_length=100, unique=True)
Course = models.CharField(max_length=100, unique=True)
def save(self, force_insert=False, force_update=False):
self.Abbreviation = self.Abbreviation.upper()
super(Courses_list, self).save(force_insert, force_update)
def __unicode__(self):
return self.Abbreviation
class Job_Posting(models.Model):
Job_Position = models.CharField(max_length=30, null=True, unique=True)
def __unicode__(self):
return self.Job_Position
class Educational_Requirement(models.Model):
fkey = models.ForeignKey('Job_Posting')
Course = models.ForeignKey('Courses_list')
And form:
class CustomField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return obj.Course
class SampleForm(ModelForm):
COURSE = CourseField(queryset=Educational_Requirement.objects.all())
I am saving at:
class MyModel(ModelForm):
course = models.CharField(max_length=50, null = True, blank = True)
In the frontend of my test app SampleForm shows the Course as choices but how do I get the actual value of Course and save it? Because when I view my saved COURSE in the admin it displays Educational_Requirement Object instead of the value I have seen on the dropdown. I can't use __unicode__ at Educational_Requirement as it would raise an error.
I have updated my answer based on your updated question.
Why not use a ManyToManyField and let Django's ORM handle the educational_requirement relationship for you? This way you can use Django's reverse lookup to handle the ForeignKey's name.
class Courses_list(models.Model):
Abbreviation = models.CharField(max_length=100, unique=True)
Course = models.CharField(max_length=100, unique=True)
def save(self, force_insert=False, force_update=False):
self.Abbreviation = self.Abbreviation.upper()
super(Courses_list, self).save(force_insert, force_update)
def __unicode__(self):
return self.Abbreviation
class Meta:
verbose_name = 'Course'
verbose_name_plural = 'Courses'
class Job_Posting(models.Model):
Job_Position = models.CharField(max_length=30, null=True, unique=True)
educational_requirement = models.ManyToManyField(Courses_list)
def __unicode__(self):
return self.Job_Position
class Meta:
verbose_name = 'Job Position'
verbose_name_plural = 'Job Positions'

django: more models with the same fields and admin interface

I have a card model with some workouts models, each workouts has exactly the same data: exercise name, repetitions..etc The workouts are 7, one for each day of the week. So I wrote 7 models with exactly the same data, in this way in the admin model I have 7 workouts and for each I can add "+" how many exercises I want (using inlines)
Is there a way to write the workout model only once and then have the possibility to add it many times in the admin interface? (each time I add a workout, I would like to be able to add exercise name, repetitions etc.. in the same admin view)
class Card(models.Model):
number = models.IntegerField()
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
trainer = models.CharField(max_length=50, blank=True, null=True)
#Card status
creation = models.DateField(auto_now_add=True)
expiration = models.DateField(blank=True, null=True)
#Member status
subscription = models.DateField(blank=True, null=True)
def __str__(self):
return u'%s %s' % (self.surname, self.name)
class Meta:
unique_together = (("number"),)
class Exercise(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return u'%s' % (self.name)
class Series(models.Model):
number = models.IntegerField()
def __str__(self):
return u'%s' % (self.number)
class Meta:
verbose_name = 'Series'
verbose_name_plural = 'Series'
class Repetitions(models.Model):
number = models.IntegerField()
def __str__(self):
return u'%s' % (self.number)
class Meta:
verbose_name = 'Repetition'
verbose_name_plural = 'Repetitions'
class Executions(models.Model):
mode = models.CharField(max_length=50)
def __str__(self):
return u'%s' % (self.mode)
class Meta:
verbose_name = 'Execution'
verbose_name_plural = 'Executions'
class Rest(models.Model):
time = models.IntegerField()
def __str__(self):
return u'%s' % (self.time)
class Meta:
verbose_name = 'Rest'
verbose_name_plural = 'Rest'
class Exercise1(models.Model):
card = models.ForeignKey(Card)
exercise = models.ForeignKey(Exercise)
series = models.ForeignKey(Series)
repetitions = models.ForeignKey(Repetitions)
executions = models.ForeignKey(Executions)
rest = models.ForeignKey(Rest)
class Meta:
verbose_name = 'Exercise'
verbose_name_plural = 'Workout 1'
def __str__(self):
return u'%s' % (self.exercise)
class Exercise2(models.Model):
card = models.ForeignKey(Card)
exercise = models.ForeignKey(Exercise)
series = models.ForeignKey(Series)
repetitions = models.ForeignKey(Repetitions)
executions = models.ForeignKey(Executions)
rest = models.ForeignKey(Rest)
class Meta:
verbose_name = 'Exercise'
verbose_name_plural = 'Workout 2'
def __str__(self):
return u'%s' % (self.exercise)
class Exercise3(models.Model):
card = models.ForeignKey(Card)
exercise = models.ForeignKey(Exercise)
series = models.ForeignKey(Series)
repetitions = models.ForeignKey(Repetitions)
executions = models.ForeignKey(Executions)
rest = models.ForeignKey(Rest)
class Meta:
verbose_name = 'Exercise'
verbose_name_plural = 'Workout 3'
def __str__(self):
return u'%s' % (self.exercise)
class Exercise4(models.Model):
card = models.ForeignKey(Card)
exercise = models.ForeignKey(Exercise)
series = models.ForeignKey(Series)
repetitions = models.ForeignKey(Repetitions)
executions = models.ForeignKey(Executions)
rest = models.ForeignKey(Rest)
class Meta:
verbose_name = 'Exercise'
verbose_name_plural = 'Workout 4'
def __str__(self):
return u'%s' % (self.exercise)
class Exercise5(models.Model):
card = models.ForeignKey(Card)
exercise = models.ForeignKey(Exercise)
series = models.ForeignKey(Series)
repetitions = models.ForeignKey(Repetitions)
executions = models.ForeignKey(Executions)
rest = models.ForeignKey(Rest)
class Meta:
verbose_name = 'Exercise'
verbose_name_plural = 'Workout 5'
def __str__(self):
return u'%s' % (self.exercise)
thanks for code, now it's more clearly.
In my opinion all your database structure ( created through django ORM models ) is incorrect, based on DRY and build database standards.
So I will show you how this database should looks for me. Only one more thing, you should using __unicode__ method instead of __str__ (link).
class Card - it's ok
class Exercise - it's provide only name field. why ? don't know, but I suggest to change the name of this class to ExerciseType, and I will tell you why later :)
Series, Repetitions, Executions, Rest - similar to Exercise model, provides only one field per model, and value of the each field is not very unique.
Exercise1-5 - name of the model should be Exercise, and has extra field named exercise_type, or type.
Look below:
class Card(models.Model):
number = models.IntegerField()
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
trainer = models.CharField(max_length=50, blank=True, null=True)
#Card status
creation = models.DateField(auto_now_add=True)
expiration = models.DateField(blank=True, null=True)
#Member status
subscription = models.DateField(blank=True, null=True)
def __unicode__(self):
return u'%s %s' % (self.surname, self.name)
class Meta:
unique_together = (("number"),)
class ExerciseType(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return u'%s' % (self.name)
class Exercise(models.Model):
type = models.ForeignKey(ExerciseType)
card = models.ForeignKey(Card)
#instead of FK, better solutions is to use normal value-field
series = models.IntegerField()
repetitions = models.IntegerField()
executions = models.CharField()
rest = models.IntegerField()
#here comes methods like __unicode__ etc ....
So, as a result, we have 3 models ( tables ) instead of 11, much simpler sql query ( without 6 SQL joins. Functionality is the same ( I hope :) ).If you have any question, just ask me I will try to help.
hope this helps.

Categories