Python Django request.GET.get method for urls with if statements - python

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.

Related

Way to Filter by DB Field in Django using Class Views

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

How can I filter items in DjangoRestFramework?

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

Direct assignment to the forward side of a many-to-many set is prohibited. Use product.set() instead

i'm building a small webstore , in the product page i put the order form using FormMixin and TemplateView, when i submit the order i get a "Direct assignment to the forward side of a many-to-many set is prohibited. Use product.set() instead." error
Bellow you can check the code
Models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=255, unique=True, )
description = models.TextField(max_length=1500)
class Meta:
verbose_name_plural = "categories"
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
nominal_price = models.PositiveIntegerField(verbose_name='prix normal',)
reduced_price = models.PositiveIntegerField(blank=True, null=True)
quantity = models.PositiveIntegerField(default=10)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='products')
photo = models.ImageField(upload_to="img/products/", default="img/products/user_default.png")
def __str__(self):
return self.name
class Customer(models.Model):
full_name = models.CharField(max_length=150)
address = models.CharField(max_length=1500, null=True)
phone = models.IntegerField()
city = models.CharField(max_length=100)
email = models.EmailField(null=True)
class Order (models.Model):
product = models.ManyToManyField(Product, through='OrderProduct')
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
class OrderProduct(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
Views.py
class ProductDetailView(FormMixin, TemplateView):
model = Product
template_name = 'product.html'
form_class = OrderForm
def get_success_url(self):
return reverse('index')
def post(self, request, *args, **kwargs):
context = self.get_context_data()
form = OrderForm(request.POST)
if context['form'].is_valid():
product = get_object_or_404(Product, name=self.kwargs['product_name'])
customer = form.save()
Order.objects.create(product=product, customer=customer)
return super(TemplateView, self)
def get_context_data(self, **kwargs):
context = super(ProductDetailView, self).get_context_data(**kwargs)
context['product'] = Product.objects.get(name=self.kwargs['product_name'])
context['form'] = self.get_form()
return context
urls.py
path('', views.ProductListView.as_view(), name='index'),
Did i missed something
For handling many-to-many relations, you cannot directly set the product from Order. Also you would need to create the order first before you can set or add a product:
order = Order.objects.create(customer=customer)
order.product.add(product)

Django get objects from url slug not working

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)

How can I get all models filtering by tag name in Django?

Basically I want to get a list of Post models, filtering them by the Tag objects contained in Post.tags
Here's my dumbed-down code:
def post_list(request, **kwargs):
posts = Post.objects.order_by('name')
posts.filter(tags__name__contains=kwargs["sort_val"], published=True)
return render(request, 'post_list.html', {"posts": posts})
In my models.py:
class Tag(models.Model):
name = models.CharField(max_length=10, unique=True)
class Post(models.Model):
title = models.CharField(max_length=50)
content = models.TextField()
tags = models.ManyToManyField(Tag, blank=True)
This then gives me the error:
Cannot resolve keyword 'name' into field. Choices are: content, id, tags, title

Categories

Resources