django how to rename PK field in a url [duplicate] - django

This question already has an answer here:
django use Pk field in a url
(1 answer)
Closed 4 years ago.
if anyone can help me with how to rename pk for a class(table) when I use it in the urlpattern.
(my goal is using many classes(tables ) PK in the same url and I want to know how to rename PK field for each table)
My code below is just for one class(table) for simplicity:
models.py:
class School(models.Model):
name = models.CharField(max_length=256)
principal = models.CharField(max_length=256)
location = models.CharField(max_length=256)
def __str__(self):
return str(self.name)
def get_absolute_url(self):
return reverse("basic_app:school_detail",kwargs={'pk':self.pk})
views.py:
class SchoolListView(ListView):
model = models.School
class SchoolDetailView(DetailView):
context_object_name = 'school_details'
model = models.School
template_name = 'basic_app/school_detail.html'
and my current urls.py (which I want to edit) :
urlpatterns = [
url(r'^$',views.SchoolListView.as_view(),name='school_list'),
url(r'^(?P<pk>\d+)/$',views.SchoolDetailView.as_view(),name='school_detail'),]
So my goal is to make the urls.py file look like this(school_pk instead of pk):
urlpatterns = [
url(r'^$',views.SchoolListView.as_view(),name='school_list'),
url(r'^(?P<school_pk>\d+)/$',views.SchoolDetailView.as_view(),name='school_detail'),]
I know I should add a function below class SchoolDetailView in views.py but I don’t know how ?
I am still learning so any help will be highly appreciated..Thanks in Advance

When declaring your model you can make a field primary by including primary_key=True, eg
class School(models.Model):
name = models.CharField(max_length=256, primary_key=True)
You can then use name within your URL.
I would recommend using unique slug fields.
EDIT
The URL isn't interested if it is called pk or slug or name. It is interested in the pattern. If you have a URL patterns
url(r'^(?P<slug>[\w\\-]+)/$', views.Type1View.as_view(), name="slug"),
url(r'^(?P<city>[\w\\-]+)/$', views.Type2View.as_view(), name="city"),
Both {% url 'slug' slug %} and {% url 'city' slug %} will produce a URL or /slug/ and both will call Type1View.as_view()
You need to ensure your URLs are unique.
If you want to refer to 3 tables then your url pattern is
url(r'^(?P<slug>[\w\\-]+)/(?P<slug1>[\w\\-]+)/(?P<slug2>[\w\\-]+)/$', MyView.as_view(), name="someName"),
And then within your view define def get_objects(self) or def get_queryset(self) to pick up the info you want.

Related

Getting a TypeError while trying to make a unique page in Django

I'm making a picture gallery web-app. I want to make some of displayed photos to belong to a specific collection. Each collection is supposed to have its own page that displays all of the pictures that belong to it.
The name of each unique page is supposed to be photo_collection model, which I added to the class Image in models.py. But for some reason, I get TypeError at /projects/sample_collection_name/ - photo_collection() got an unexpected keyword argument 'photo_collection'
No idea what's causing this error. I tried renaming the photo_collection function (it has the same name as my model), but it didn't work.
models.py
class Image(models.Model):
title = models.CharField(max_length=300)
image = models.ImageField(null=True, blank=True, upload_to='images/')
pub_date = models.DateTimeField('Date published', default=timezone.now)
photo_collection = models.CharField('Photo collection', max_length=250, null=True, blank=True)
views.py
def photo_collection(request):
image = Image.objects.all()
return render (request, 'photo_app/collection.html', context={'image': image})
urls.py
urlpatterns = [
#some other patterns here
path('projects/<str:photo_collection>/', views.photo_collection, name='photo_collection'),
]
gallery.html
{% if i.photo_collection != Null %}
{{i.photo_collection}}
{% endif %}
you need to add photo_collection to your view parameters.
it will be like this:
def photo_collection(request, photo_collection):
image = Image.objects.all()
return render (request, 'photo_app/collection.html', context={'image': image})
when ever you add a variable to your url path you need to add that variable to view parameters too.
here is the documentation for this matter:
https://docs.djangoproject.com/en/4.1/topics/http/urls/

Django template not displaying data from database

I am running into an issue where my database is information is displaying on one template, but I want certain parts to display on another page for a blog.
When I click into physics-blog it will display my images and post title. For this, I have looped through the database. Works fine and perfectly.
But when I click into one of them and want to show {{ physicsBlog.body }} it doesn't show anything. Which I can't wrap my head around because that works just fine in the other ListView template, but not in the DetailView template.
Here is my code.
models.py
class physicsBlog(models.Model):
title = models.CharField(max_length=250)
blog_image = models.ImageField(null=True, blank=True)
description = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = RichTextField(blank=True, null=True)
date_created = models.DateField(auto_now_add=True)
def __str__(self):
return self.title + ' | ' + str(self.author)
views.py
class physicsBlogListView(ListView):
model = physicsBlog
template_name = 'physics.html'
ordering = ['-id']
class physicsBlogDetailView(DetailView):
model = physicsBlog
template_name = 'physics-blog-details.html'
urls.py
urlpatterns = [
path('', views.home, name="home"),
path('physics-blog', physicsBlogListView.as_view(), name="physics-blog"),
path('physics-blog/<int:pk>', physicsBlogDetailView.as_view(), name="physics-blog-details"),
path('crypto-blog', cryptoBlogListView.as_view(), name="crypto-blog"),
path('crypto-blog/<int:pk>', cryptoBlogDetailView.as_view(), name="crypto-blog-details"),
]
I'm not super familiar using these generic displays that Django provides, but from the django docs it says
While this view is executing, self.object will contain the object that
the view is operating upon.
So maybe try {{ object.body }} in your template?
You can use standard way of rendering data in standard single-object view (mostly DetailView):
{{ object.body }}
But if you want to see it better, just add context_object_name variable:
class physicsBlogDetailView(DetailView):
context_object_name = "physics_blog"
...
After such change in template:
{{ physics_blog.body }}
Without context_object_name it's object or object_list. I'm kinda surprised that you did ok in ListView and had problem in DetailView, because it's the same thing.

How to change url path to name in django instead of id

sorry if I ask very a simple question, I'm just starting to learn about WebDev and I have a question about django url and I used rest framework. I have http://localhost:8000/api/projectList/1 and I want to change id to the name in the url, for example http://localhost:8000/api/projectList/project
This is the code:
model.py
class ProjectList(models.Model):
project = models.CharField(max_length=200)
project_name = models.CharField(max_length=200)
category = models.CharField(max_length=200)
academic = models.CharField(max_length=200)
view.py
class ProjectListSerializer(serializers.ModelSerializer):
class Meta :
model = ProjectList
fields = '__all__'
class ProjectListViewset(viewsets.ModelViewSet):
queryset = ProjectList.objects.all()
serializers_class = ProjectListSerializer
class ProjectListListView(generics.ListAPIView):
serializer_class = ProjectListSerializer
def get_queryset(self):
return ProjectList.objects.all()
class ProjectId(generics.RetrieveUpdateDestroyAPIView):
queryset = ProjectList.objects.all()
serializer_class = ProjectListSerializer
urls.py
urlpatterns = [
path("", include(router.urls)),
path("projectList/", ProjectListListView.as_view()),
path("projectList/<int:pk>", ProjectId.as_view()),
]
Thank you, sorry for my simple question and my bad English.
Django Rest Framework ModelViewset doesn't require to declare separate view for detail. In ProjectListListView declare
lookup_field = 'project'
and delete
path("projectList/<int:pk>", ProjectId.as_view()),
from urlpatterns
In views and serializer define lookup_field = project, this will override the default id field.
Ps - make sure project is unique and primary key.
also change your url to accept string instead of int(id)

Django url patterns for two related models

I have two models (School and Student) with one to many relationship.
my models.py are set as follows:
class School(models.Model):
name = models.CharField(max_length=256)
principal = models.CharField(max_length=256)
location = models.CharField(max_length=256)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("basic_app:school_detail",kwargs={'pk':self.pk})
class Student(models.Model):
name = models.CharField(max_length=256)
age = models.PositiveIntegerField()
school = models.ForeignKey(School,related_name='students',on_delete=models.CASCADE,default=None)
and the urls.py file will have the following:
urlpatterns = [
url(r'^$',views.SchoolListView.as_view(),name='school_list'),
url(r'^(?P<pk>\d+)/$',views.SchoolDetailView.as_view(),name='school_detail'),
url(r'^create/$',views.SchoolCreateView.as_view(),name='school_create'),
url(r'^update/(?P<pk>\d+)/$',views.SchoolUpdateView.as_view(),name='school_update'),
url(r'^delete/(?P<pk>\d+)/$',views.SchoolDeleteView.as_view(),name='school_delete'),
my question is I want to add to the urlpatterns list more urls for students:something like
#url(r'^$',views.StudentListView.as_view(),name='student_list'),
# url(r'^(?P<pk>\d+)/$',views.StudentDetailView.as_view(),name='student_detail'),
# url(r'^create/$',views.StudentCreateView.as_view(),name='student_create'),
# url(r'^update/(?P<pk>\d+)/$',views.StudentUpdateView.as_view(),name='student_update'),
# url(r'^delete/(?P<pk>\d+)/$',views.StudentDeleteView.as_view(),name='student_delete')
I know my addition is not correct because each group of students should be related to a specific school. I am confused how to use id/pk in the url because for example student_detail.html url should contain both school id and student id.
sorry if this looks naive question.. but I am still learning and any help will be highly appreciated..
thanks
You could add another argument school_pk to the URL pattern, for example:
url(r'^school/(?P<school_pk>\d+)/update/(?P<pk>\d+)/$',views.StudentUpdateView.as_view(),name='student_update'),
Then filter the queryset to only include students from that school.
class StudentUpdateView(UpdateView):
def get_queryset(self):
queryset = super(StudentUpdateView, self).get_queryset()
return queryset.filter(school=self.kwargs['school_pk'])
The UpdateView will take care of fetching the student, because you're still using pk for the student pk.
You need to add 'student(s)' to the urls to make them distinct. You may not need to add school_id to student urls as they are related by ForeignKey
url(r'^students$',views.StudentListView.as_view(),
name='student_list'),
url(r'^student/(?P<pk>\d+)/$',views.StudentDetailView.as_view(),
name='student_detail'),
url(r'^student/create/$',views.StudentCreateView.as_view(),
name='student_create'),
url(r'^student/update/(?P<pk>\d+)/$',views.StudentUpdateView.as_view(),
name='student_update'),
url(r'^student/delete/(?P<pk>\d+)/$',views.StudentDeleteView.as_view(),
name='student_delete')

Viewing subset of objects in Django, Views, URLs, Models

I know this is a very basic concept in Django, and I have tried the tutorial but it is not working. I am working on a comic book database with the models set like this (at least, a sample of two of the models):
Class Title(models.Model):
title = models.CharField(max_length=256)
vol = models.IntegerField("Vol.")
slug = models.SlugField(blank=True, null=True)
#desc = models.CharField(max_length=256)
class Meta:
ordering = ['title']
def get_absolute_url(self):
return "/comics2/title/%s" % self.slug
def __unicode__(self):
return self.title
class Issue(models.Model):
title = models.ForeignKey(Title)
number = models.IntegerField(help_text="Enter the number only. Do not include the hashtag.")
writer = models.ManyToManyField(Creator)
What I am trying to do is create a page that shows a list of all the issues within that Title.
But, I have it setup in the views like this:
class AstonishingXMenIssueListView(ListView):
context_object_name = "astonishing_list"
queryset = Issue.objects.filter(title__title="Astonishing X-Men").order_by("number")
template_name = "comics2/astonishing_list.html"
My urls.py look like this:
(r'^comics2/title/(?P<title_slug>[-\w]+)/$', AstonishingXMenIssueListView.as_view(
)),
Of course, going to /uncanny-xmen-v1/ shows the same thing as the Astonishing link above.
Obviously, this is not a practical way to list issues by title for future issues and titles, so I need it setup so that I don't have to individually do this. Now, I have tried following the Django generic views tutorial, but I got an index tuple error.
I've tried this, but it doesn't work. This is what gets me the index tuple error.
class IssuesByTitleView(ListView):
context_object_name = "issues_by_title_list"
template_name = "comics2/issues_by_title.html",
def get_queryset(self):
title = get_object_or_404(Title, title__iexact=self.args[0])
return Issue.objects.filter(title=title)
Any ideas? And can someone please reply in baby-language, as I am new to Django and Python, so simply telling me to look at the Tutorial again isn't going to help. So, maybe writing out the code would help! Thanks!
Generally, your IssueByTitleView is the right way to do it. But as you use named groups in your URL regex (the (?P<title_slug>[-\w]+) part of your URL), you have to access the URL parameters through self.kwargs instead of self.args. Also, you have to filter on the slug field, not the title field:
title = get_object_or_404(Title, slug=self.kwargs['title_slug'])