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.
Related
For example, there have two class in Django model:
class Generus(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
LIST_KLP = (
('Marbar', 'Marbar'),
('Marsel', 'Marsel'),
)
klp = models.CharField(max_length=6, choices=LIST_KLP, default='Marbar')
def __str__(self):
return self.user.first_name
class Event(models.Model):
LIST_EVENT = (
('Mince', 'Mince'),
('Persami', 'Persami'),
)
name_event = models.CharField(max_length=20, choices=LIST_EVENT, default='Persami')
attendance = models.ManyToManyField(Generus, related_name='foo', blank=True)
def __str__(self):
return '%s %s' % (self.jenis_kegiatan, self.tanggal)
From those class, I want to get the number of the attendance which has the klp = Marsel. Is there any possible solution?
I believe you should be able to do...
Event.objects.filter(foo__klp='Marsel')
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)
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'
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
I have one to many relationship with model Year and it has a foreign key with another model Compound. I am trying to get the Django admin widget to include the class name so that it can be pulled from the drop down /autocomplete.
I have it something like
def __unicode__(self):
return u'(%s) %d' % (self.compound.compound_name, self.year)
But this doesn't return the compound name as I expect but all attribute in the model compound.
class Year(models.Model):
compound = models.ForeignKey('Compound', blank=False, null=False)
year = models.PositiveSmallIntegerField(blank=True, null=True)
def __unicode__(self):
return u'(%s) %d' % (self.compound.compound_name, self.year)
class Compound(models.Model):
dif_id = models.CharField(max_length=50, blank=True, default='UnKnown')
type = models.CharField(max_length=50, blank=True, default='SM')
compound_name = models.CharField(max_length=100, blank=True, default='UnKnown')
phase = models.PositiveSmallIntegerField(db_index=True, default=0)
def __unicode__(self):
return u'%s %s %s %d' % (self.dif_id,self,type,self.compound_name,self.phase )
class Meta:
verbose_name_plural = 'Compounds'
Any idea how I should get the compound_name?
And also, I am looking to improve it by checking if the compound_name is Unknown the display the dif_id .
Thanks