I am working on a django project and I have 2 models that look like this:
class Playlist(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,related_name='playlist_user')
name = models.CharField(max_length=120)
image = models.ImageField(upload_to=upload_image_path)
genre = models.CharField(max_length=120,null=True,blank=True)
track = models.ManyToManyField('Post',related_name='playlist_track')
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
title = models.CharField(max_length=120)
slug = models.SlugField(unique=True)
image = models.ImageField(upload_to=upload_image_path)
audiofile = models.FileField(upload_to=upload_image_path,null=True)
genre = models.CharField(max_length=120,null=True,blank=True)
and this view:
def userprofileview(request):
own_tracks = Post.objects.filter(user=request.user)
playlist_ = Playlist.objects.filter(user=request.user)
context = {
'own_tracks':own_tracks,
'playlist_':playlist_
}
return render(request,'userprofile.html',context)
but when I try to query the posts from the playlist like this:
{% for object in playlist_ %}
{{ object.track }}
{% endfor %}
I get:
posts.Post.None
Thank you for any suggestions
In order to access the related objects, you need to add .all at the end:
{% for object in playlist_ %}
{% for post in object.track.all %}
{{ post.title }}
{% endfor %}
{% endfor %}
To avoid the N+1 problem, you can use .prefetch_related(..) [Django-doc]:
def userprofileview(request):
own_tracks = Post.objects.filter(user=request.user)
playlist_ = Playlist.objects.filter(user=request.user).prefetch_related('post')
context = {
'own_tracks':own_tracks,
'playlist_':playlist_
}
return render(request,'userprofile.html',context)
Related
i am creating an website where a user can search for recipes by their ingredients. I wish that when a user finally see recipe, ingredients there would be splited with ', ' in view. for now it is just space. I tried to do this in my model, but they i get error as in title
- 'CharField' object has no attribute split.
Models:
from django.db import models
class Ingredient(models.Model):
ingredient_name = models.CharField(max_length=250)
igredient_name1 = ingredient_name.split(', ')
def __str__(self):
return self.ingredient_name1
class Recipe(models.Model):
recipe_name = models.CharField(max_length=250)
preparation = models.CharField(max_length=1000)
ingredients = models.ManyToManyField(Ingredient)
def __str__(self):
return self.recipe_name
template:
<div>
<h1>Drink drank drunk</h1>
</div>
{% for drink in results %}
<div>
<p>{{ drink.recipe_name }}</p>
<p>Preparation: {{ drink.preparation }}</p>
<p>Ingredients:
{% for ingredient in drink.ingredients.all %}
{{ingredient.ingredient_name}}
{% endfor %}
</p>
</div>
{% endfor %}
view:
def drink_list(request):
template = "drinks/drink_list.html"
return render(request, template)
def search_results(besos):
query = besos.GET.get('q')
q = Q()
for queries in query.split(', '):
q |= (Q(ingredients__ingredient_name__icontains=queries))
results = Recipe.objects.filter(q)
template = "drinks/search_results.html"
context = {
'results' : results,
}
return render(besos, template, context)
After some mess understanding what is needed to accomplish it seems that the solution is just to add the desired comma into the template, modifying the forloop as follows:
{% for ingredient in drink.ingredients.all %}}
{{ingredient.ingredient_name}}{% if not forloop.last %},{% endif %}
{% endfor %}
I am trying to display a checklist in the CreateView using the values in the ForeignKey fields for descriptions.
models.py
class Structure(models.Model):
name = models.CharField(max_length = 30)
description =models.CharField(max_length = 300, null=True, blank=True)
def __str__(self):
return self.name
class SelectedFramework(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
structure = models.ForegignKey(Structure)
selected = models.BooleanField(default = False)
views.py
class FrameworkCreateView(generic.CreateView):
model = SelectedFramework
fields =['structure', 'selected']
template_name = 'catalogue/structure.html'
def form_valid(self, form):
form.instance.user = self.request.user
return super(FrameworkCreateView, self).form_valid(form)
structure.html
{% extends 'catalogue\base.html' %}
{% block container %}
<h2>{% block title %}Structures{% endblock title %}</h2>
<form action="" method="post">
{% csrf_token %}
{% for field in form %}
<div class="col-sm-10">{{form.structure}} {{form.selected}}</div><br>
{% endfor %}
</div>
</form>
{% endblock %}
The code above works but will display the ForeignKey 'structure' as a dropdown list with the values of __str__. Is there a way to display string for structure.name and structure.description with the checkbox from selected in the CreateView?
In your template use:
{{ form.structure.name }}
{{ form.structure.description}}
You can write custom form, override the save method and create Structure object manually there:
class FrameworkForm(forms.ModelForm):
structure_name = forms.CharField(required=True)
structure_description = forms.CharField(required=False)
class Meta:
model = SelectedFramework
fields = [
'structure_name', 'structure_description', 'selected'
]
def save(self, commit=False):
instance = super(FrameworkForm, self).save(commit=False)
structure = Structure(
name=self.cleaned_data.get('structure_name'),
description=self.cleaned_data.get('structure_description')
)
structure.save()
instance.structure = structure
instance.save()
return instance
Also add form_class = FrameworkForm to your view instead of fields = ['structure', 'selected']
EDIT:
Perhaps you want something like this:
<ul>
{% for structure in form.fields.structure.choices.queryset %}
<li>{{ structure.name }} - {{ structure.description }}</li>
{% endfor %}
</ul>
If you want to get fields by iterating in the template. You have to use-
{% for field in form %}
{{ field }}
{% endfor %}
don't have to use any dot notation to get the field. If you want to get the label of the field you can use {{ field.label}} usually before {{field}}
I have a list of tools that have a part added as a bundle. The bundle is listed as a part in a many-to-many field, so I need to iterate over the parts to see if the add-on product exists for the tool being displayed. If the part exists, then I want to display just the part itself. I've tried working it out with the code below and it does check if it exists, but prints out the queryset. I understand the .all() is the cause of this but I can't figure out how to check and then just display the single part. Thank you for your help.
{% for p in tool.parts.all %}
{% if 'bp-01' %}
<h3>Bundle Included:</h3>
{{ p.model_number }}
...
{% endif %}
{% endfor %}
Part Model
class Part(Timestamp):
model_number = models.ForeignKey(ModelNumber)
price = models.SmallIntegerField()
title = models.CharField(max_length=250)
slug = models.SlugField(help_text="slug-title-should-be-like-this")
description = RichTextField()
type = models.ForeignKey(Type, blank=True)
category = models.ForeignKey(Category)
Tool Model
class Tool(Timestamp):
model_number = models.ForeignKey(ModelNumber)
price = models.SmallIntegerField()
title = models.CharField(max_length=250)
slug = models.SlugField(help_text="slug-title-should-be-like-this")
description = RichTextField()
type = models.ForeignKey(Type)
category = models.ForeignKey(Category)
parts = models.ManyToManyField(Part, blank=True, related_name="parts")
Model Number Model
class ModelNumber(models.Model):
slug = models.SlugField(max_length=100, unique=True, help_text="slug-title-should-be-like-this")
class Meta:
verbose_name = 'Model Number'
verbose_name_plural = 'Model Numbers'
def __str__(self):
return self.slug
If you just have slug field on ModelNumber you can use {% if p.model_number.slug== 'bp-01' %} to check for the condition:
{% for p in tool.parts.all %}
{% if p.model_number.slug == 'bp-01' %}
<h3>Bundle Included:</h3>
{{ p.model_number }}
...
{% endif %}
{% endfor %}
Depending on how your ModelNumber model looks, you can compare the values with something like this:
{% for p in tool.parts.all %}
{% if p.model_number.number == 'bp-01' %}
<h3>Bundle Included:</h3>
{{ p.model_number }}
...
{% endif %}
{% endfor %}
This is assuming that ModelNumber looks something like this:
class ModelNumber(models.Model):
number = models.CharField(max_length=20)
....
def __str__(self):
return self.number
I'm working on multi-user rss reader. I want to limit display of posts only to those which are unread. I've managed to do this in my single "feed" view as below, but I can't figure out how to do the same in multiple feed aka "category" view.
I've been trying something like here https://docs.djangoproject.com/en/1.5/topics/db/queries/#spanning-multi-valued-relationships but it didn't work for me
Should I change my "category" view code or template code? and if so how would you go about it?
thanks!
-S
models
class UserCategory(models.Model):
name = models.CharField(unique=False, max_length=64)
user = models.ForeignKey(User)
slug = AutoSlugField(populate_from='name', always_update='True', unique_with='user')
class Feed(models.Model):
feed_url = models.URLField(unique=True)
default_title = models.CharField(max_length=64, blank=True)
link = models.URLField(blank=True)
class UserFeed(models.Model):
feed = models.ForeignKey(Feed)
title = models.CharField(max_length=64)
category = models.ForeignKey(UserCategory)
user = models.ForeignKey(User)
slug = AutoSlugField(populate_from='title', always_update='True', unique_with='user')
class Post(models.Model):
feed = models.ForeignKey(Feed)
title = models.CharField(max_length=256)
content = models.TextField()
link = models.URLField(max_length=512)
class ReadPost(models.Model):
user = models.ForeignKey(User)
post = models.ForeignKey(Post)
views
def feed(request, user_feed_slug):
user_feed = get_object_or_404(UserFeed.objects.filter(slug=user_feed_slug, user=request.user))
read_post = ReadPost.objects.filter(user=request.user).values_list('post')
posts = Post.objects.select_related().filter(feed=user_feed.feed).exclude(id__in=read_post)
def category(request, user_category_slug):
user_category = get_object_or_404(UserCategory.objects.filter(slug=user_category_slug, user=request.user))
templates
feed
{% for post in posts %}
{{ post.title }}
{% endfor %}
category
{% for feed in user_category.userfeed_set.all %}
{{ feed.title }}
{% for post in feed.feed.post_set.all %}
{{ post.title }}
{{ post.content }}
{% endfor %}
{% endfor %}
You can write custom template filter, i.e:
#register.filter
def unread(posts, read_posts):
return posts.exclude(id__in=read_posts)
(before you must pass read_post to category template context).
Try this queryset:
def category(request, user_category_slug):
user_category = get_object_or_404(UserCategory, slug=user_category_slug,
user=request.user))
feeds = UserFeed.objects.filter(category__slug=user_category_slug, user=request.user)\
.prefetch_related('feed__post_set')
then in your template:
{% for feed in feeds %}
{{ feed.title }}
{% for post in feed.feed.post_set.all %}
{{ post.title }}
{{ post.content }}
{% endfor %}
{% endfor %}
I'm been trying to figure out how could I query forthe most liked whiteboard for a particular category
At the moment i'm been querying for all the whiteboards objects for a particular category.
One of my solutions was to query by the boards by the counts of liked but I just couldn't think of a way to query for it
An example at the moment I can retrieve all the whiteboard objects for a particular category , Now how could I retrieve the most liked whiteboard for a particular category.
Can someone help me create function that would query the most liked board of the category so I can understand logically how I can create my own later .Thank you
class WhiteBoard(models.Model):
ENGLISH = 'ENGLISH'
MATH = 'MATH'
SCIENCE = 'SCIENCE'
BIOLOGY = 'BIOLOGY'
CATEGORY = (
(ENGLISH , 'English'),
(MATH, 'Math'),
(SCIENCE, 'Science'),
(BIOLOGY, 'Biology'),
)
Category =models.CharField(max_length=30,choices=CATEGORY)
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
picture = models.OneToOneField('Picture',related_name='picture',blank=True,null=True)
def __unicode__(self):
return self.name
class LikeBoard(models.Model):
user = models.ForeignKey(User)
Whiteboard = models.ForeignKey(WhiteBoard)
created = models.DateTimeField(auto_now_add=True)
My views.py
def WhiteBoardFinder(request):
form = WhiteBoardFinderForm(request.POST)
fo = WhiteBoardFinderForm()
if form.is_valid():
Category = form.cleaned_data['Category']
Whiteboard = WhiteBoard.objects.filter(Category=Category)
return render(request,"boardfinder.html",{"board":board,"fo":fo})
return render(request,"boardfinder.html",{"fo":fo})
boardfinder.html
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ fo.as_p }}
<input type = "submit" value= "Find Board" />
</form>
{% if board %}
<ul>
{% for b in board %}
<li><a href ="{% url world:Boat b.id %}">{{ b.name }}</li>
{% if b.picture %}
<br><img src="{{ b.picture.image.url }}">
{% endif %}
{% endfor %}
</ul>
{% endif %}
My forms.py
class BoardFinderForm(forms.ModelForm):
class Meta:
model = WhiteBoard
fields = ('Category',)
models.py
class WhiteBoard(models.Model):
ENGLISH = 'ENGLISH'
MATH = 'MATH'
SCIENCE = 'SCIENCE'
BIOLOGY = 'BIOLOGY'
CATEGORY = (
(ENGLISH , 'English'),
(MATH, 'Math'),
(SCIENCE, 'Science'),
(BIOLOGY, 'Biology'),
)
Category =models.CharField(max_length=30,choices=CATEGORY)
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
picture = models.OneToOneField('Picture',related_name='picture',blank=True,null=True)
def __unicode__(self):
return self.name
#property
def count_likes(self):
return LikeBoard.objects.filter(whiteboard=self).count()
class LikeBoard(models.Model):
user = models.ForeignKey(User)
whiteboard = models.ForeignKey(WhiteBoard) //modified because of conflict
created = models.DateTimeField(auto_now_add=True)
views.py
def WhiteBoardFinder(request):
form = WhiteBoardFinderForm(request.POST)
fo = WhiteBoardFinderForm()
if form.is_valid():
Category = form.cleaned_data['Category']
whiteboard = WhiteBoard.objects.filter(Category=Category)
categories = WhiteBoard.objects.values_list('Category', flat=True).distinct()
whites = sorted(whiteboard, key=lambda x: x.count_likes, reverse=True)
return render(request,"boardfinder.html",{
"board":board,"fo":fo, "categories": categories, "whites": whites})
return render(request,"boardfinder.html",{"fo":fo})
templates
{% for category in categories %}
{{ category }}<br/>
{% for white in whites %}
{% if white.Category == category %}
{{ white }} - {{ white.count_likes }},
{% endif %}
{% endfor %}<br/>
{% endfor %}