I'm trying to get the category of a skill in a template.
From the post I read, I can't directly get information from a foreign key in a template.
Instead, I add a function on CharacterSkill models to get the Skill category
Models.py
class Character(models.Model):
name = models.CharField(max_length=70)
class Skill(models.Model):
name = models.CharField(max_length=70)
cat1 = '01'
SKILLSET_CHOICE = ((cat1:'cat1'))
skillset_choice = models.CharField(
max_length=2,
choices = SKILLSET_CHOICE,
default='',
blank=True,
null=True,
)
class CharacterSkill(models.Model):
character = models.ForeignKey(Character, on_delete=models.CASCADE)
skill = models.ForeignKey(Skill, on_delete=models.CASCADE)
def skillcategory(self):
return Skill.objects.get(id = self.skill).skillset_choice
Template
skillsetchoice {{item.skillcategory}}
But I get an error :
Exception Type: TypeError
Exception Value:
int() argument must be a string or a number, not 'Skill'
I tried to inpect value with the shell console where I can get back the category id but when I use it in template, nothing is working
Hope you can help me!
This has nothing to do with calling it from the template.
self.skill is already an instance of Skill. There is no need to query that model explicitly.
def skillcategory(self):
return self.skill.skillset_choice
And in fact this method is pretty pointless; you certainly can do it directly in the template:
skillsetchoice {{ item.skill.skillset_choice }}
Replace self.skill with self.skill.id (in older versions of Django your code would work by the way):
def skillcategory(self):
return Skill.objects.get(id = self.skill.id).skillset_choice
But this is much better:
def skillcategory(self):
return self.skill.skillset_choice
But do you really need this method? You can use:
{{ item.skill.skillset_choice }}
If you want to display cat1, then (get_foo_display):
{{ item.skill.get_skillset_choice_display }}
Related
I am working a on projects using Django. Here is my models.py :
class Owner(models.Model):
name = models.CharField(max_length=200)
class Cat(models.Model):
owner = models.ForeignKey(Owner, on_delete=models.CASCADE)
pseudo = models.CharField(max_length=200)
I did that :
first_owner = Owner.objects.get(id=1)
And I would like to do something like that
first_owner.Cat
to get all the cats from an owner
I know I can do something like that :
first_cat = Owner.objects.get(id=1)
owner = first_cat.owner
But I would like the reverse operation without using ManyToMany field because every cats has an only owner in my case.
My aim is to do that using only one query.
You can add related_name in your model and use it for get all objects referenced as ForeignKey from the given field like below:
class Cat(models.Model):
owner = models.ForeignKey(Owner, on_delete=models.CASCADE,
related_name='cats') #---> you can put whatever related_name you want
pseudo = models.CharField(max_length=200)
and query it like this:
first_owner = Owner.objects.get(id=1)
all_instances = first_owner.cats.all()
You will get all objects referenced as ForeignKey in your Cats model.
To get all Cat instances from Owner instance in the view you can do:
first_owner = get_object_or_404(Owner,id=1)
all_instances = first_owner.cat_set.all()
In the template you can do it as:
{% for owner in first_owner.cat_set.all %}
{{owner.psuedo}}
{% endfor %}
I have been trying for too long now to get my urls working with my simple models and view. There is something I am definitely not understanding.
I wish to create a url similar to:
.../department/team,
where I do not use the PK of department object but the name instead.
My model looks like:
class Department(models.Model):
name = models.CharField(max_length=50, blank=True, null=True)
def __str__(self):
return 'Department: ' + self.name
class Hold(models.Model):
name = models.CharField(max_length=50, blank=True, null=True)
department = models.ForeignKey(Department, on_delete=models.CASCADE)
my view looks like (UPDATED):
class IndexView(generic.ListView):
template_name = 'index.html'
context_object_name = 'departments_list'
def get_queryset(self):
return Department.objects.all()
class DepartmentView(generic.DetailView):
model = Department
template_name="depdetail.html"
slug_field = "name"
slug_url_kwarg = "name"
my url looks the following: UPDATED
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<name>', views.DepartmentView.as_view(), name='depdetail')
]
and finally my html:
<h1> Hello there {{ object.name }} student</h1> </br>
<b> Choose your team:<b> </br>
however i keep getting page not found or must be slug or pk..
I hope someone can help me out so I can wrap my head around this.
UPDATED
It works now :) Thank you for the replies.
By default Django will look for a pk or a slug field when you use a DetailView. You must override get_object() method to change this behaviour:
get_object() looks for a pk_url_kwarg argument in the arguments to the view; if this argument is found, this method performs a primary-key based lookup using that value. If this argument is not found, it looks for a slug_url_kwarg argument, and performs a slug lookup using the slug_field.
That being said, your approach has other problems. It is always better to use a slug instead of a name for other reasons. For example, name is not guaranteed to be unique and also it may have characters which are not URL safe. See this question for a detailed discussion on how to use slug fields.
I have a model with method.
class Book(models.Model):
title = models.TextField()
class Review(models.Model):
content = models.TextField()
book = models.ForeignKey(Book,related_name="book_reviews")
def lastreview(self):
return self.objects.order_by('-id')[:1]
but once I use this method in template
{{book.book_reviews.lastreview.content}}
it is showing nothing..
what am i missing here?
I believe you are trying to retrieve the latest review of a book (which was not clear from your question). The related reviews for a book can be accessed by book.book_reviews. It is a QuerySet rather than a single Review object, hence {{ book.book_reviews.lastreview }} will fail.
I would recommend moving the lastreview method directly under Book, like:
class Book(models.Model):
title = models.TextField()
def lastreview(self):
try:
return self.book_reviews.order_by('-id')[0]
except IndexError:
return None
Now you can access the latest review of a book in your template by
{{ book.lastreview.content }}
Note: I recommend adding a DateTimeField to Review, as finding the latest review based on id can be misleading. For e.g., someone can edit an old review and it will not be shown as the latest.
I have defined a relationship between two models of different app using foreign key and data is inserted into Db accurately with foreign key instance, but I want to fetch that data using Django ORM but I didn't get it, I have googled this issue and also checked stack-overflow questions but still my issues are not solved.
#models.py
class teamInfo(models.Model):
ownerID = models.IntegerField()
teamName = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.id)
class gameWorld(models.Model):
team = models.ForeignKey(teamInfo)
w = models.IntegerField(null=True)
l = models.IntegerField(null=True)
def __unicode__(self):
return unicode(self.id)
I have tried a few things in my views but nothing worked for me. Here is the latest thing I have tried in my views:
def teamStandings(request,template=None,context=None):
getAllTeamStat = gameWorld.objects.all()
for i in getAllTeamStat.teaminfo_set.select_related() :
raise Exception(i.teaminfo.teamName)
I simply want a Django ORM query which fetches data from both models so I can display the team name in templates
See here and try that:
class TeamStandingsView(ListView):
model = gameWorld
template = # Some template path here!
context_object_name = "games"
in template:
{% for game in games %}
{{ game.team.teamName }}
{% endfor %}
edit: this should work:
def teamStandings(request,template=None,context=None):
getAllTeamStat=gameWorld.objects.all()
for team in getAllTeamStat:
for teaminfo in team.teaminfo_set.all():
print teaminfo.teamName
I want to model a situation and I´m having real trouble handling it. The domain is like this: There are Posts, and every post has to be associated one to one with a MediaContent. MediaContent can be a picture or a video (for now, maybe music later). So, what I have is:
mediacontents/models.py
class MediaContent(models.Model):
uploader = models.ForeignKey(User)
title = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
def draw_item(self):
pass
class Meta:
abstract = True
class Picture(MediaContent):
picture = models.ImageField(upload_to='pictures')
class Video(MediaContent):
identifier = models.CharField(max_length=30) #youtube id
posts/models.py
class Post(models.Model):
...
# link to MediaContent
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
media_content = generic.GenericForeignKey('content_type', 'object_id')
What i eventually want to do, is beeing able to call methods like:
post1.media_content.draw_item()
>> <iframe src="youtube.com" ...>
post2.media_content.draw_item()
>> <img src="..."/>
Is this the correct aproach, does it work? Can the template be agnostic of the object underneath?
Your approach looks good to me. You just need to override the draw_item method in your Picture and Video models. Your template will look something like
{% for post in posts %}
{{ post.media_content.draw_item }}
{% endfor %}
and it doesn't matter which model the generic foreign key points to, as long as it has a draw_item method defined.