Here is the thing i'm trying to do:
There are few tv channels as image links and they will have some information inside channels.
I managed to create tv channels as a list, they look like a link but they don't work like link.
I've created slug area for each channel that takes from it's own name and generates slug auto. And with get_absolute_url i take it's url in the below code you'll see;
This is my model :
class Channels(models.Model):
name = models.CharField(max_length=50, null=False, blank=False, verbose_name="Tv Kanalı")
logo = models.ImageField(upload_to="channels/images/", verbose_name="Tv Logosu", blank=False)
slug = models.SlugField(null=True, unique=True, editable=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Channels, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('channel-list:campaigns', kwargs={'page_slug': self.slug})
This is my main urls:
urlpatterns = [
path('admin/', admin.site.urls),
url(r'', include(('tvekstra.apps.core.urls', 'home'), namespace='home')),
url(r'^user/', include(('tvekstra.apps.user.urls', 'login'), namespace='user')),
url(r'^channels/', include(('tvekstra.apps.tvchannels.urls', 'main'), namespace="channel-list")),
This is channels urls:
urlpatterns = [
url(r'', views.channel_list, name='channels'),
url(r'^(?P<page_slug>[-\w]+)/$', views.campaign_list, name='campaigns'),
]
This is my views:
def channel_list(request):
channels = Channels.objects.all()
return render(request, 'channel.list.html', {'channels': channels})
def campaign_list(request, page_slug):
channel = get_object_or_404(Channels, slug=page_slug)
return render(request, 'campaign.list.html', {'channel': channel})
And this is my template:
{% for channel in channels %}
<div class="col-3 text-center channels">
<a href="{{ channel.get_absolute_url }}">
<img src="{{ channel.get_image }}" alt="Channel Image" class="ch-img">
{{ channel.name }}
</a>
</div>
{% endfor %}
As you can see, a href is channel's getabsoluteurl method. It creates the html but it doesn't go forward page.
I think view is not working for some reason, requesting aid...
url(r'', matches '', but it also matches /channels/fox/ and /something-else/.
You can fix it by adding ^$ to the regex.
url(r'^$', views.channel_list, name='channels'),
In Django 2.0+, it would be better to use re_path, because url is deprecated in Django 3.1:
re_path(r'^$', views.channel_list, name='channels'),
And it would be simpler to use path:
path('', views.channel_list, name='channels'),
Related
I am working on my first solo project with Django and I have hit a problem that no amount of searching and reading similar post on SO have solved.
I am trying to filter a gallery of images by their category, so that when the user clicks on a picture it will result in a page showing all the images with the same category. This will use HTMX hopefully in the final product, but I'm trying and failing to implement it using regular Django views initially.
As I said, this is my first solo project, so I'm very much a beginner, I know this isn't a debug service but just wanted some pointers on where I could be going wrong. Another set of eyes as you will.
I followed the docs on dynamic filtering CBV. I have overwritten get_queryset passing the Category slug into the kwargs and I have overwritten the get_context_dataso I can pass slug into the template.
I am getting a Reverse for 'select' with arguments '('',)' not found. 1 pattern(s) tried: ['select/(?P<slug>[-a-zA-Z0-9_]+)\\Z'] error, so I belive the problem is in my template/URLconf.
Models. Media with a FK to it's Category
class Category(models.Model):
title = models.CharField(max_length=200, null=True)
slug = AutoSlugField(populate_from='title')`
class Media(models.Model):
timestamp = models.DateTimeField()
image = models.ImageField(upload_to="media")
url = models.URLField()
order = models.IntegerField(default=0)
visable = models.BooleanField(default=True)
categories = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, blank=True)
Views, IndexView is entire gallery and SelectView is image by category
class IndexView(ListView):
template_name = "main/index.html"
model = Media
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context ['main_images'] = Media.objects.filter(visable=True)
return context
class SelectView(ListView):
template_name = "main/select.html"
model = Media
def get_queryset(self):
self.category = get_object_or_404(Category, title=self.kwargs['slug'])
return Media.objects.filter(categories__title=self.category)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['slug'] = self.category
return context
URLconf with select being the relevant pattern.
app_name = "main"
urlpatterns = [
path("", views.IndexView.as_view(), name="home"),
path("about", views.AboutView.as_view(), name="about"),
path("contact", views.ContactView.as_view(), name="contact"),
path("select/<slug:slug>", views.SelectView.as_view(), name="select"),
]
Gallery template I have a for loop to display the IndexView. I think the problem is with the Href (which I want to take my to SelectView). I am passing slug in the {% url %} but think it should be image.categories__slug? I have tried this but it still doesn't work. I am stumped.
{% for image in main_images %}
<div class="cbp-item web-design print">
<a href="{% url "main:select" slug %}" class="cbp-caption cbp-singlePageInline">
<div class="cbp-caption-defaultWrap"> <img src="{{ MEDIA_URL }} {{ image.image.url }}"alt=""> </div>
{% endfor %}
Many thanks.
I think what you want is to access the slug field on the image.categories field for each iteration.
{% for image in main_images %}
...
<a href="{% url 'main:select' image.cateogries.slug %}" class="cbp-caption cbp-singlePageInline">
...
{% endfor %}
In addition to that, I'd recommend that you do a lookup for the receiving slug instead of the title on the Category model. For example, if you should save I love this day as the title, the slug field would have I-love-this-day.
What you have:
def get_queryset(self):
self.category = get_object_or_404(Category, title=self.kwargs['slug'])
return Media.objects.filter(categories__title=self.category)
title=self.kwargs['slug'] won't find a title if your passing I-love-this-day as the slug. I'd suggest using slug=self.kwargs['slug']. See the below updates:
def get_queryset(self):
# Also, the self keyword is not needed here either -> self.category
category = get_object_or_404(Category, slug=self.kwargs['slug']) # updated
return Media.objects.filter(categories__title=category.title) # updated
Additionally, I see where you're passing slug as a value via the context variable within the SelectView... I suggest you pass the category object explicitly via the context variable to the template where you can access the fields from your template if necessary.
Within the get_context_data():
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# context['slug'] = self.category
context['category'] = get_object_or_404(Category, slug=self.kwargs['slug'])
return context
I'm having a huge issue on making for loop on django templates,for some reasone it dont show on the page the categories that i create on database
urls.py
app_name = 'statenews'
urlpatterns = [
path('', views.home, name="home"),
path('', views.category, name = 'category'),]
models.py
class Category(models.Model):
name = models.CharField(max_length=65)
...
class News(models.Model):
...
category = models.ForeignKey(
Category, on_delete=models.SET_NULL, null=True, blank=True,
default=None,
)
views.py
def category(request):
categories = Category.objects.all()
return render(request,'partials/footer.html',{
'categories': categories
})
html template
<div class="col-lg-3 col-md-6 mb-5">
<h4 class="font-weight-bold mb-4">Tags</h4>
{% for category in categories %}
<div class="d-flex flex-wrap m-n1">
({category.name})
</div>
{% endfor %}
</div>
You have two url paths with same url. Change it to:
urlpatterns = [
path('', views.home, name="home"),
path('categories', views.category, name = 'category')
]
Then enter via yourdomain.com/categories. Otherwise it will always show home view.
EDIT:
In you homepage you can simply see home view as it is set in url with ''. If you want to see categories as footer part, then you have to change your home template, render it with {% include 'partials/footer.html' %}. Then you have to pass categories in home view context.
Disclaimer.....this is an assignment!
Can someone tell me why I am getting
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/%7B%20%25%20url%20'detail'%20user%20%25%20%7D
Using the URLconf defined in bobbdjango.urls, Django tried these URL patterns, in this order:
[name='home']
profile [name='profile']
user_detail/<str:user_id> [name='detail']
The current path, { % url 'detail' user % }, didn’t match any of these.
You’re seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
I think its a problem with my URL but I am not seeing source of error. I would just like to click on the link on the home page and move to the user details page. See code below...
My Home page
<body>
{% block content %}
<h1>This is home page</h1>
<div>
<!-- Your profile -->
{% for user in users %}
<a href="{ % url 'detail' user % }">
<h3>{{user.first_name}}</h3>
</a>
{% endfor %}
</div>
{% endblock %}
</body>
My main URL
urlpatterns = [
## path('admin/', admin.site.urls),
path('', include('bobbpets.urls') ),
## path('bobbpets/<int:user.id/>', views.userDetails, name='userDetails'),
]
My app URL
urlpatterns = [
## path('admin/', admin.site.urls),
path('', views.home, name='home'),
path('profile', views.profile, name='profile'),
path('user_detail/<str:user_id>', views.userdetail, name='detail'),
]
My Views
def home(request):
users = User.objects.all()
return render(request, 'home.html', {'users': users})
def userdetail(request,user_id):
user = User.objects.get(id=user_id)
return render(request, 'user_detail.html', {'user': user})
def profile(request):
return render(request, 'profile.html')
My Model
from django.db import models
class User(models.Model):
first_name=models.CharField(max_length=30)
last_name=models.CharField(max_length=30)
email=models.EmailField()
def __str__(self):
return '{} {}'.format(self.first_name, self.last_name)
Your template URL should look like this: <a href="{% url 'detail' user %}
Remove the spaces that you have between your percent signs and parenthesis. That will cause an error.
Try this:
<a href="{ % url 'detail' user.id % }">
but I think you should change
'user_detail/<str:user_id>'
as
'user_detail/<int:user_id>'
I am trying to add an Item to a list view, the UserPost list view has already a Post context.
In my project, a user can add a post and add an item each is a different app with different models.
So In my UserPost list view, I have my Posts looped related to a specific user related to it.
What I am trying to do is check if this post.user has an item filtered by the same user and if it does exist a button show appears in the page linking to another page with this list of items related to this user.
To be more descriptive I want to check for Item for the designer__post and link to this page which is {% url 'core:designer-posts' item.designer %}
I hope this clears my question if there are any more clarifications required or code please let me know to add it.
I tried to use make use of an Exists subquery [Django-doc] but I didn't succeed it perfecting it
Here is the models.py
class Post(models.Model):
designer = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
Here is the views.py
class UserPostListView(ListView):
model = Post
template_name = "user_posts.html"
context_object_name = 'posts'
queryset = Post.objects.filter(admin_approved=True)
paginate_by = 6
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(designer=user, admin_approved=True).order_by('-date_posted')
Here is the template user_posts.html
{% if item %}
<a class="primary btn-lg" href="{% url 'core:designer-posts' item.designer %}" role="button">Go to items</a>
{% else %}
<a href="{% url 'core:designer-posts' item.designer %}">
<button type="button" class="btn btn-primary btn-lg btn-block">Go to items</button>
</a>
{% endif %}
here is the item models.py
class Item(models.Model):
designer = models.ForeignKey(
User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
here is the designerlist views.py that I am trying to link to from the user post view if it is available
class DesignerPostListView(ListView):
model = Item
template_name = "designer_posts.html"
context_object_name = 'items'
paginate_by = 6
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Item.objects.filter(designer=user).order_by('-timestamp')
Here are the views related to the post model
app_name = 'score'
urlpatterns = [
path('', PostListView.as_view(), name='score'),
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
]
Here are the views related to the item model
app_name = 'core'
urlpatterns = [
path('', HomeView.as_view(), name='home'),
path('user/<str:username>', DesignerPostListView.as_view(),
name='designer-posts'),
]
Projects URLs
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('allauth.urls')),
path('', include('core.urls', namespace='core')),
path('score/', include('score.urls', namespace='score')),
path('register/', user_views.register, name='register'),
]
First, you need to pass one context variable by overriding the get_context_data(...) method, that decides whether the user has Items or not
class UserPostListView(ListView):
# rest of your code
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
has_items = Item.objects.filter(designer__username=self.kwargs['username']).exists()
context['has_items'] = has_items
return context
Then in your template, use this has_items variable by,
{% if has_items %}
<a class="primary btn-lg" href="{% url 'core:designer-posts' username=view.kwargs.username %}" role="button">Go to items</a>
{% endif %}
Also, you were not passing the username to the url tag, it should be
{% url 'core:designer-posts' username=view.kwargs.username %}
here, I used view.kwargs.username to get the username from the URL
References
ListView.get_context_data(...)
url tag with kwargs
in {% url %} item.designer passes a user object you have to provide id for that like this
<a href="{% url 'core:designer-posts' item.designer.id %}">
i am a beginner in Django. i have the below simple django model (refer to below). My list view has worked perfectly fine in the https://localhost/simpleapp/. However, when i try DetailView via https:local host/simpleapp/1, it gives me a 404 cant found. I don't know where is the problem as i already defined the urls wit the regular expression ^(?P\d+)/$.
Model.py
class University(models.Model):
university_name = models.CharField(max_length = 50)
def __str__(self):
return self.university_name
class Student(models.Model):
last_name = models.CharField(max_length = 50)
first_name = models.CharField(max_length = 50)
age = models.PositiveIntegerField()
university = models.ForeignKey(University, on_delete=True)
def __str__(self):
return '{} {}'.format(self.first_name, self.last_name)
Views.py
class StudentList(generic.ListView):
model = models.Student
context_object_name = 'student_list'
template_name = 'simpleapp/student_list.html'
class StudentDetail(generic.DetailView):
model = models.Student
context_object_name = 'student_detail'
template_name = 'simpleapp/student_detail.html'
urls.py in app folder
urlpatterns = [
url(r'^$', views.StudentList.as_view(), name='student_list'),
url(r'^(?P<pk>\d+)/$', views.StudentDetail.as_view(), name='student_detail'),
]
urls.py in project folder
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^$', views.Index.as_view(), name='index' ),
url(r'^simpleapp/$', include('simpleapp.urls', namespace='simpleapp')),
]
student_detail.html
{% extends 'simpleapp/student_base.html' %}
{% block content %}
<h1> {{student_detail}}</h1>
{% endfor %}
{% endblock %}
You have a $ at the end of the pattern that includes the simpleapp urls, which means nothing more will be matched. So the basic /simpleapp/ URL works, but anything after that won't. Remove that $; only use it on full patterns, not includes.
url(r'^simpleapp/$', include('simpleapp.urls', namespace='simpleapp')),
Here Django will match all urls which begin with simepleapp/ (because of the beginning ^) and ends with it as well (because of the ending $).
/simpleapp/1 is not matched by the url matcher.
instead, try changing the url to
url(r'^simpleapp/', include('simpleapp.urls', namespace='simpleapp')),
this way, Any url starting with simepleapp will be matched