I'm trying to make it so that I can show only briefs with the slug name as the category, however it does not work.
At the minute I can only use it by showing all briefs using .objects.all() however this is not suitable for my desired use case.
Do i need a slug field in the brief section too?
Models.py
class Category(models.Model):
name = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=50, unique=True)
class Meta:
verbose_name_plural = 'categories'
verbose_name = 'category'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('browse')
class Brief(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
brandname = models.CharField(max_length=28)
description = models.CharField(max_length=200)
date = models.DateTimeField(auto_now=True, blank=True)
category = models.ForeignKey(Category, on_delete=CASCADE)
def get_absolute_url(self):
return reverse('homepage')
Urls.py
path('browse/categories/<slug:catslug>/', views.postsinthecategory, name = 'catslug'
views.py
def postsinthecategory(request, catslug):
categories = Category.objects.all()
brief = Brief.objects.all()
if catslug:
category = get_object_or_404(Category, slug = catslug)
brief = Brief.objects.get(category=catslug)
template = 'users/categoryposts.html'
context = {'categories': categories, 'brief': brief, 'category': category}
return render(request, template,context)
You can use __slug to filter on the related model's slug field. Use filter instead of get, because you want a queryset that can contain more than brief. I would rename brief to briefs in your view to make that clearer.
briefs = Brief.objects.filter(category__slug=catslug)
Or, since you fetched the category on the previous line, you could do:
category = get_object_or_404(Category, slug = catslug)
briefs = Brief.objects.filter(category=category)
Related
I tried to search for answers, but after a few days, I'm here asking:
I'm a beginner, making a todo list app - expanding on a tutorial I followed. Currently, it's filtering by user, which is fine, but I also want to filter by a field in the DB (list).
Models:
class ToDoList(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
title = models.CharField(max_length=200)
description = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Meta:
ordering = ['created']
class Task(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
title = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
list = models.ForeignKey(ToDoList, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Meta:
ordering = ['complete']
View I'm trying to change:
class TaskList(LoginRequiredMixin, ListView):
model = Task
context_object_name = "tasks"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['tasks'] = context['tasks'].filter(user=self.request.user)
context['count'] = context['tasks'].filter(complete=False).count
search_input = self.request.GET.get('search-area') or ''
if search_input:
context['tasks'] = context['tasks'].filter(title__startswith=search_input)
context['search_input'] = search_input
return context
Also, is there a way to access the list variable in the html component, like here?
url:
path('tasks/<list>/create', TaskCreate.as_view(), name="task-create"),
html:
← Back
I am complete beginner and I made a django project a while ago. Its main purpose is adding restaurants and categories and food menu respectively. For now, it is working well, if I go to the required restaurant, it shows its categories. But now, I want to improve it via Vuejs and that's why I'm trying to make Django REST API. But I can't filter categories and food according to their restaurant, because category model is not directly connected to restaurant model. My models.py is:
from django.db import models
from django.conf import settings
class Restaurant(models.Model):
owner = models.OneToOneField(settings.AUTH_USER_MODEL, related_name="restaurant", on_delete=models.CASCADE)
name = models.CharField(max_length=256, db_index=True)
slug = models.SlugField(max_length=256, unique=True)
logo = models.ImageField(upload_to='logos/', blank=True)
def __str__(self):
return str(self.name)
class Category(models.Model):
name = models.CharField(max_length=256, db_index=True)
slug = models.SlugField(max_length=256, unique=True)
icon = models.ImageField(upload_to='categories/', blank=True)
class Meta:
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return str(self.name)
class Food(models.Model):
restaurant = models.ForeignKey(Restaurant, related_name='foods', on_delete=models.CASCADE)
category = models.ForeignKey(Category, related_name='foods', on_delete=models.CASCADE)
name = models.CharField(max_length=256, db_index=True)
slug = models.SlugField(max_length=256, blank=True)
price = models.IntegerField(default=0)
description = models.TextField(blank=True)
image = models.ImageField(upload_to='foods/', blank=True)
available = models.BooleanField(default=True)
def __str__(self):
return str(self.name)
As you see, category class is not directly connected to restaurant. It is filtered with views.py. My views.py is:
from django.shortcuts import render, get_object_or_404
from .models import Restaurant, Category, Food
def food_list(request, restaurant_slug, category_slug):
restaurant = get_object_or_404(Restaurant, slug=restaurant_slug)
category = get_object_or_404(Category, slug=category_slug)
foods = Food.objects.filter(restaurant=restaurant, category=category, available=True)
categories = set(list(Category.objects.filter(foods__restaurant=restaurant)))
return render(request, 'restaurant/food_list.html', {'restaurant': restaurant, 'category': category, 'foods': foods, 'categories': categories})
def category_list(request, restaurant_slug=None):
restaurant = get_object_or_404(Restaurant, slug=restaurant_slug)
categories = set(list(Category.objects.filter(foods__restaurant=restaurant)))
return render(request, 'restaurant/category_list.html', {'restaurant': restaurant, 'categories': categories})
As I mentioned above it is working well now. But I want to GET categories and food respect to their restaurants. How to filter it with Django REST API?
Example code of filtering in Django :
class PassengerList(generics.ListCreateAPIView):
model = Passenger
serializer_class = PassengerSerializer
# Show all of the PASSENGERS in particular WORKSPACE
# or all of the PASSENGERS in particular AIRLINE
def get_queryset(self):
queryset = Passenger.objects.all()
workspace = self.request.query_params.get('workspace')
airline = self.request.query_params.get('airline')
if workspace:
queryset = queryset.filter(workspace_id=workspace)
elif airline:
queryset = queryset.filter(workspace__airline_id=airline)
return queryset
I want to display product detail page using drf but I keep running into one error after another.
urls.py
path('product/<int:id>', views.product_detail_view.as_view(), name='product-detail'),
models.py
class Product(models.Model):
categories = models.ManyToManyField(Category)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="product_owner")
item = models.CharField(max_length=150)
slug = models.SlugField(max_length=255, blank=True, null=True)
brand = models.CharField(max_length=255, default="brand")
image = models.ImageField(upload_to="images/products/")
label = models.CharField(max_length=254, default='', blank=True, null=True)
serializers.py
class product_detail_serializer(serializers.ModelSerializer):
category = serializers.SerializerMethodField()
class Meta:
model = Product
fields = ("id", "categories", "item", "slug", "image")
lookup_field = "id"
def get_category(self, obj):
return obj.get_category_display()
views.py
class product_detail_view(generics.RetrieveAPIView):
serializer_class = product_detail_serializer
lookup_field = "id"
The error I'm getting now is 'Product has no attribute 'get_category_display'
Please how do I fix this error?
You can try defining the id inside the product_detail_serializer class then include it in the url patterns path like this:
serializers.py
class product_detail_serializer(serializers.ModelSerializer):
category = serializers.SerializerMethodField()
id = serializers.IntegerField(read_only=True)
Then include the id in the urlpatherns path
path('product/<int:id>',views.product_detail_view.as_view(),name='product
detail'),
I basically can't explain why this worked. I used the serializer for product instead of creating another serializer for the product detail page.
I have a table name "Like" and column named "value". It contains two values, either "Like" or "Unlike". How do i get the column value with only "Like" using Like.objects.values(). I have tried,
query = Like.objects.values({'value': 'Like'}).order_by().annotate(Count('value'))
It's throwing,
AttributeError: 'dict' object has no attribute 'split'
The objective is to get the no of likes in descending order. If i get it using object.values(), I can do something like below to sort,
sorted_dec = sorted(query, key=lambda x:x['value'], reverse=True)[0:5]
Or is there any better logic to approach this?
models.py:
class Post(models.Model):
title = models.CharField(max_length=100)
content = RichTextField(blank=False, null=True, validators=[MinLengthValidator(200)])
liked = models.ManyToManyField(User, default=None, blank=True, related_name = 'liked')
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name = 'author')
def __str__(self):
return self.title
#property
def num_likes(self):
return self.liked.all().count()
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
LIKE_CHOICES = (
('Like', 'Like'),
('Unlike', 'Unlike'),
)
class Like(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
value = models.CharField(choices= LIKE_CHOICES,default='Like', max_length=10)
def __str__(self):
return str(self.post)
The following query will give you the queryset containing dictionaries in it.
query = Like.objects.filter(value='Like').values()
I'd like to filter the posts by its two different categories which are schools and category.
models.py
class Category(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=100, unique=True)
class Meta:
ordering = ('name',)
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.name
class School(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=100, unique=True)
class Meta:
ordering = ('name',)
verbose_name = 'school'
verbose_name_plural = 'schools'
def __str__(self):
return self.name
class VideoPost(models.Model):
category = models.ForeignKey('Category', on_delete=models.CASCADE)
school = models.ForeignKey('School', on_delete=models.CASCADE)
title = models.CharField(max_length=100)
slug = models.SlugField(max_length=100, unique = True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
video = models.CharField(max_length=100, blank=True)
content = RichTextUploadingField()
image = models.ImageField(upload_to='images', null=True, blank=True)
date_posted = models.DateTimeField(default=timezone.now)
def _get_unique_slug(self, *args, **kwargs):
self.slug = slugify(self.title)
super(VideoPost, self).save(*args, **kwargs)
def __unicode__(self):
return self.title
School and Category are the foreignKeys for VideoPost. So, in the db it would only have its ids, not the slug or name. Which are category_id & school_id
views.py
def post_list(request):
school = request.GET.get('school', None)
category = request.GET.get('category', None)
posts = VideoPost.objects.all()
if school:
posts.filter(school=school).order_by('-date_posted')
elif category:
posts.filter(category=category).order_by('-date_posted')
elif school & category:
posts.filter(school=school).filter(category=category).order_by('-date_posted')
else:
posts.order_by('-date_posted')
## I wanted to filter them in multiple ways where the posts are filtered by either one of the category, or both, but It doesn't work.
## The only way I found that's working is:
posts = VideoPost.objects.all().filter(school=school).filter(category=category)
##This way, it filtered the posts with its school and category id specified.
return render(request, 'stories/browse.html', {'posts': posts})
template.html
Link
So, my questions are
Would it be possible to have text in the db for foreign key? So that url can be more readable, and I could use text in url tag.
like Link
How could I use request.GET.get() method with IF statement properly?
You can filter the VideoPost by school slug and category slug, you don't need to make the slug field primary key, usually this is a bad design. What you can do is to make the slug field unique, so you know there is no entries with the same slug.
Remember that every filter apply to a QuerySet will return a new QuerySet, so you can create a chain of QuerySet.
The following code should work as expected
school_slug = request.query_params.get('school', None)
category_slug = request.query_params.get('category', None)
posts = VideoPost.objects.all()
if school:
# If we have school, filter by school slug
posts = posts.filter(school__slug=school_slug)
if category:
# If we have category, filter by category slug
posts = posts.filter(category__slug=category_slug)
# Always order the posts by date_posted
posts = posts.order_by('-date_posted')
return render(request, 'stories/browse.html', {'posts': posts})
If both school and category are passed then we apply 2 filter to the queryset
Also, in the future I'll suggest to use django-filter for this use cases.