Django href for html - django

How i can make link to this urls.py? I tried to pass the link through all the methods I know but they don't work and gave an error
path('category/<slug:gender_slug>/<slug:category_slug>/', views.StuffCategory.as_view(), name='category'),
html:
{% get_genders as genders %}
{% for gender in genders %}
<li>
<!-- First Tier Drop Down -->
<label for="drop-2" class="toggle">Категории <span class="fa fa-angle-down"
aria-hidden="true"></span> </label>
{{ gender }} <span class="fa fa-angle-down" aria-hidden="true"></span>
<input type="checkbox" id="drop-2">
<ul>
{% get_categories as categories %}
{% for category in categories %}
<li>{{category.name}}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
views.py
class StuffCategory(ListView):
model = Stuff
template_name = 'shop/shop.html'
context_object_name = 'stuffs'
def get_queryset(self):
queryset = Stuff.objects.filter(draft=False)
if self.kwargs.get('category_slug'):
queryset = queryset.filter(category__slug=self.kwargs['category_slug'])
if self.kwargs.get('gender_slug'):
queryset = queryset.filter(gender__slug=self.kwargs['gender_slug'])
return queryset

Just pass the parameters that have been defined in url as below:
{{category.name}}
For more information refer to official docs

When trying to access a link with a href attribute you can simply use the name attribute of your path object that you defined in urls.py. You have to make sure, to submit every parameter the path object needs:
For example for an edit field:
<li><a href="{% url 'category' object.pk gender_slug=gender arg %}">
here:
category is the name
object.pk could be the primary key of the object transmitted to the template
gender_slug & arg are additional parameters that are defined by your path object

Related

Getting ValuError: Field 'id' expected a number but got a html

I am a newcomer, about 10 days into a self-taught Django, and I am building a Django (v3.2) app.
The main view in the app is a list of countries (view: CountryListView, template: countries_view.html).
When I click on a country in that list, a detail view is brought up to see detailed country data (CountryDetailView and country_detail.html).
In CountryDetailView, there are navigation buttons: either back to CountryListView, or 'Edit', which shall bring the user to CountryEditView, where the country parameters can be changed & saved.
However, when I click on 'Edit', I get the following error:
Request Method: GET
Request URL: http://127.0.0.1:8000/manage_countries/countries/country_edit.html/
Django Version: 3.2.4
Exception Type: ValueError
Exception Value: Field 'id' expected a number but got 'country_edit.html'
I am guessing this might to do something with values returned (or rather expected but not returned) from CountryDetailView, but what they are? And how to make CountryDetailView to return the object id? (I am using plain integer id's in my model)
views.py
class CountryListView(LoginRequiredMixin, ListView):
model = Countries
context_object_name = 'countries_list'
template_name = 'manage_countries/countries_view.html'
class CountryDetailView(LoginRequiredMixin, DetailView):
model = Countries
template_name = 'manage_countries/country_detail.html'
class CountryEditView(LoginRequiredMixin, UpdateView):
model = Countries
template_name = 'manage_countries/country_edit.html'
success_url = reverse_lazy('manage_countries:countries_view')
urls.py
path('', CountryListView.as_view(),name='countries_view'),
path('countries/<pk>/', CountryDetailView.as_view(), name='country-detail'),
path('<pk>/edit', CountryEditView.as_view(), name='country_edit'),
countries_view.html
{% block content %}
<div class="list-group col-6">
Click here to add country data
{% for country in countries_list %}
<small><span class="text-dark">{{ country.name }}</span></small>
{% endfor %}
</div>
{% endblock content %}
country_detail.html, with two navigation buttons (back to the list), and further to Edit form (this is the one that does not work).
{% block content %}
<div class="card col-5 shadow-mt">
<h5 class="card-header bg-light text-center">Country data</h5>
<div class="card-body">
<table class="table">
<thead><tr>
<th scope="col"><small>Name: </small></th>
<th scope="col"><small>{{ object.name }}</small></th>
</tr></thead>
</table>
<button class="btn btn-secondary mt-3" onclick="javascript:history.back();">Back</button>
<button class="btn btn-secondary mt-3" onclick="window.location.href='../country_edit.html';">Edit</button>
</div>
</div>
{% endblock content %}
Your onclick attribute of button contains invalid url:
<button>onclick="window.location.href='../country_edit.html';">Edit</button>
Use instead template tag url (Django Docs):
<button class="btn btn-secondary mt-3" onclick="window.location.href='{% url 'country_edit' object.pk %}';">Edit</button>

Django - Can't display category and sub category in template html

How can display category and sub category in product template?
what is missing in below code
This is a part of View.py according product view, shows filtering category and subcategory from model.py.
class ProductView(View):
def get(self,request,*args,**kwargs):
categories=Categories.objects.filter(is_active=1)
categories_list=[]
for category in categories:
sub_category=SubCategories.objects.filter(is_active=1,category_id=category.id)
categories_list.append({"category":category,"sub_category":sub_category})
merchant_users=MerchantUser.objects.filter(auth_user_id__is_active=True)
return render(request,"admin_templates/product_create.html",{"categories":categories_list,"merchant_users":merchant_users})
this is part of model.py according model after migrate,
class Products(models.Model):
id=models.AutoField(primary_key=True)
url_slug=models.CharField(max_length=255)
subcategories_id=models.ForeignKey(SubCategories,on_delete=models.CASCADE)
product_name=models.CharField(max_length=255)
brand=models.CharField(max_length=255, default="")
product_max_price=models.CharField(max_length=255)
product_discount_price=models.CharField(max_length=255)
product_description=models.TextField()
productTemplate.html
<div class="col-lg-6">
<label>Category</label>
<select name="sub_category" class="form-control">
{% for category in categories %}
<optgroup label={{ category.category.title }}>
{% for sub_cat in category.sub_category %}
<option value="{{ sub_cat.id }}">{{ sub_cat.title }}</option>
{% endfor %}
</optgroup>
{% endfor %}
</select>
</div>
I implemented this solution and I will teach you step by step how to implement it. Rather, a spoiler of what we will learn:
With that in mind, let's get our hands dirty:
The first thing we will need to do is return the published categories to our template . In the file views.pyin the method of receita, where we return the receita.htmlchosen recipe to the template , which is also the page that displays the categories select, we will create a filter to return the published categories to us. And we can do this with the following code:
categorias = Receita.objects.filter(publicada=True).values('categoria').distinct('categoria')
See, through the Recipes object we filter all the recipes that have the true flag for published. After that, we just get the category values. So we say to django: - django, returns me only the recipes that have true for published, but I just want the category column . And the distinct? To serve? The distinct will guarantee us that there will be no repetition in the data. Example:
If the filter returns to us that the category column has: dessert, salty, dessert, soup, salty ... what the distinct will do is to avoid repeated data, with that we will only have: dessert, salty, soup. How are you?
In possession of that, we need to pass this value to our dictionary that will go to the context of our template:
receita_a_exibir = {
'receita': receita,
'categorias': categorias
}
Note that we pass to the 'categories' key the value of our filter that was saved in the categories variable.
Now we can move the dictionary into context:
return render(request, 'receita.html', receita_a_exibir)
Great, now we can access the categories in our template receita.html'
And to display them we can go through each category and put the name of that category in our select. Also remembering that we need to redirect the url to our search route when we click on the search button:
<div class="receipe-post-search mb-80">
<div class="container">
<form action="{% url 'buscar' %}">
<div class="row">
<div class="col-12 col-lg-5">
<select type="text" name="buscar">
{% for categoria in categorias %}
<option value="{{categoria.categoria}}">{{categoria.categoria}}</option>
{% endfor %}
</select>
</div>
<div class="col-12 col-lg-2 text-right">
<button type="submit" class="btn delicious-btn">Buscar</button>
</div>
</div>
</form>
</div>
Now, with our template ready, you will be able to see the categories in the select.
The next step is to modify our search method so that it can search by category and not just the name of the recipe as it used to.
In views.py, in the method of buscar, let's say to django: search for the name of the recipe or all the recipes in that category. We can do this through the object Q used to set up queries where we will have more than one possible answer :
lista_receitas = lista_receitas.filter(Q(nome_receita__icontains=nome_a_buscar) | Q(categoria__icontains=nome_a_buscar))
That is, filter the recipes that have that name or that have that category. And in order to Qwork, we will need to import it:
from django.db.models import Q
You can test it! With these modifications you will be able to use the select categories.
Summary of modified files:
views.py file
from django.db.models import Q
.
def buscar(request):
lista_receitas = Receita.objects.filter(publicada=True).order_by('-data_receita')
if 'buscar' in request.GET:
nome_a_buscar = request.GET['buscar']
if buscar:
lista_receitas = lista_receitas.filter(Q(nome_receita__icontains=nome_a_buscar) | Q(categoria__icontains=nome_a_buscar))
dados = {
'receitas' : lista_receitas,
}
return render(request, 'buscar.html', dados)
.
def receita(request, receita_id):
receita = get_object_or_404(Receita, pk=receita_id)
categorias = Receita.objects.filter(publicada=True).values('categoria').distinct('categoria')
receita_a_exibir = {
'receita': receita,
'categorias': categorias
}
return render(request, 'receita.html', receita_a_exibir)
.
Recipe.html file
.
<div class="receipe-post-search mb-80">
<div class="container">
<form action="{% url 'buscar' %}">
<div class="row">
<div class="col-12 col-lg-5">
<select type="text" name="buscar">
{% for categoria in categorias %}
<option value="{{categoria.categoria}}">{{categoria.categoria}}</option>
{% endfor %}
</select>
</div>
<div class="col-12 col-lg-2 text-right">
<button type="submit" class="btn delicious-btn">Buscar</button>
</div>
</div>
</form>
</div>
Some django documentation references:
Distinc
Object Q
I hope I helped you

how do i create a profile page that shows all users post to the user and to other users

am new to Django and am trying to create a blog site where users can sign up and post articles, but my problem is how can I display a user's post on the user's profile page so that when other users reading the post clicks on the author's name it takes them to the post.author's profile page with the post.author's recent post listed and not the request.user's post. here is my code.
here is accounts/views.py
views.py
#login_required()
def user_profile_view(request, username):
post = User.objects.filter(courses__author=username)
context = {'courses': courses}
return render(request, 'accounts/user_profile_view.html', context)
and here is post/models.py
models.py
class Posts(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
cover = ProcessedImageField(upload_to='post_featured_image',
processors=[ResizeToFill(600, 300)],
format='png',
options={'quality': 80},
blank=True)
slug = models.SlugField()
title = models.CharField(max_length=200)
body = models.TextField()
summary = models.TextField(max_length=200)
here is the template
post_list.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="col-lg-6">
{% for course in courses_list %}
<div class="central-meta item">
<div class="user-post">
<div class="friend-info">
{% if post.author.profile.avatar %}
<figure>
<img src="{{ post.author.profile.avatar.url }}" alt="">
</figure>
{% else %}
<img src="{% static 'default.ico' %}" alt="">
{% endif %}
<div class="friend-name">
<ins>{{ course.author.get_full_name|title }}</ins>
<span>published: {{ post.published }}</span>
</div>
<div class="post-meta">
{% if course.cover %}
<img src="{{ post.cover.url }}" alt="">
{% endif %}
<div class="friend-name">
<ins>{{ course.title|title }}</ins>
</div>
<div class="description">
<p><span>{{ post.summary|capfirst }}</span></p>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
here is my accounts/urls.py
urls.py
app_name = 'accounts'
urlpatterns = [
path('accounts/profile/<str:username>/', user_profile_view, name='user_profile'),
]
you should be able do that, easy and via lots of ways.
make a post model like this:
class Post(models.Model):
author = foreign_key(User, related_name="posts", on_delete=models.CASCADE)
title = char_field()
content ........
so with that related name you will be able to reverse from user to its posts too!.
in your template do this:
{{ post.author }}
this link will redirect user to the posts author dashboard if you arrange the urls pattern correctly.
then for sorting authors posts, you have to pass the dashboard_owner to the template and use this name instead of user which normally will refer to the request.user -> user who are visiting the page
{% for post in dash_owner.posts.all %}
<li> <a href="{{ post.get_abslute_url }}" target="_blink">
{{ post.title }} </a> </li>
{% endfor %}
in views.py
def dashboard(request, owner_id=None)
if owner_id:
dash_owner = get_or_404(User, id=owner_id)
elif request.user.is_authenticated:
dash_owner = User.objectd.get(id=request.user.id)
return render(request, 'dashboard.html', {'dash_owner': dash_owner})
in urls.py -> urlpatterns:
path('dashboard/<int:owner_id>/', views.dashboard, name="dashboard")
this is the idea behind that, but for get the better result, you may need to clearly define the get_absolute_url of User model, to give you the url which machts to
'dashboard/<int:id/'
or another way is instead of that, do this:
{{ post.author }}

Django templates iterate model fields with indices

I have the follow model:
class UserProfile(...):
...
photo1 = models.URLField()
photo2 = models.URLField()
photo3 = models.URLField()
photo4 = models.URLField()
photo5 = models.URLField()
And in the Create/Update template, I have to write five copies of the following div for file1 to file5:
<div>
Photo 1:
{% if userProfileForm.instance.file1 %}
<a href="{{ userProfileForm.instance.file1 }}" target=_blank>View</a>
{% endif %}
<input type=file name=file1>
{% if userProfileForm.instance.file1 %}
Delete
{% endif %}
</div>
Is there a way to iterate field file<i>?
{% for i in '12345' %}
<div>
Photo {{ forloop.counter }}:
...
</div>
{% endfor %}
in django you have _meta API. So I think this solves your problem if you use get_fields method (and maybe you will filter desired fields out).
hope it helps.
update with example
let me show how you should solve your problem:
desired_fields = []
for field in UserProfile._meta.get_fields()
if "photo" in field.name:
desired_fields.append(field.name)
context.update(fields=desired_fields) # pass it in the context
at this point you have your desired fields which should be used with for loop in the template. And one more thing, you would need to add some template tag to get real field from string representation:
# custom template tag
def from_string_to_field(instance, field_str):
return getattr(instance, field_str, None)
and in the template code will look like this
{% for field in fields %}
{{userProfileForm.instance|from_string_to_field:"field"}}
{% endfor %}

Count objects assigned to the category in a django cycle

I've a cycle in my template, which get's all the categories
like this:
<div class="panel">
<h4 class="title1">Категории</h4>
<ul class="clear-list">
{% for categ in categs %}
<li>
{{ categ.name }}
</li>
{% endfor %}
</ul>
</div>
And my views.py looks like:
def adverts(request):
args = {}
args.update(csrf(request))
args['adverts'] = Advert.objects.all().order_by('-advert_date', '-id')
args['sections'] = AdvertSection.objects.all().order_by('-name')
args['categs'] = AdvertCategory.objects.all().order_by('-name')
args['username'] = auth.get_user(request).username
return render_to_response('adverts.html', args)
Now comes question....
How to show total count of objects attached to the category?
Output:
Category1
Category2
Category3
Expected Output:
Category1(115)
Category2(546)
Category3(832)
Please help me...
Assuming the objects attached to your categories are called Adverts:
{% for categ in categs %}
{{ categ.name }} ({{ categ.advert_set.count }})
{% endfor %}
If you changed the attribute related_name of your Adverts in the Category ModelClass in your models.py file you'll have to adjust advert_set to the corresponding related_name.
For more information about how to access related objects take a look at the docs.