Что такое pk в django
Перейти к содержимому

Что такое pk в django

  • автор:

Как получить pk из url в django rest framework?

У меня есть 2 приложения Ticket и Comment, с url: http://127.0.0.1:8000/api/tickets//comments// .

class CommentAPIList(ListCreateAPIView): queryset = Comment.objects.all() serializer_class = CommentSerializer permission_classes = (IsAuthenticatedOrReadOnly,) pagination_class = CommentAPIListPagination 

Я хочу получить первый int:pk в моем url для фильтрации моего набора запросов, например:

queryset = Comment.objects.filter(ticket=MY_GOAL_PK) 
class Comment(models.Model): text = models.TextField() ticket = models.ForeignKey( Ticket, on_delete=models.CASCADE, ) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, ) time_create = models.DateTimeField(auto_now_add=True) time_update = models.DateTimeField(auto_now=True) def __str__(self): return self.text 
class Ticket(models.Model): title = models.CharField(max_length=150) text = models.TextField() status = models.ForeignKey(Status, on_delete=models.PROTECT, default=2) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, ) time_create = models.DateTimeField(auto_now_add=True) time_update = models.DateTimeField(auto_now=True) def __str__(self): return self.title 

get_queryset(…) :

class CommentAPIList(ListCreateAPIView): queryset = Comment.objects.all() serializer_class = CommentSerializer permission_classes = (IsAuthenticatedOrReadOnly,) pagination_class = CommentAPIListPagination def get_queryset(self, *args, **kwargs): return ( super() .get_queryset(*args, **kwargs) .filter(ticket_id=self.kwargs['ticket_pk']) )

Для пути первичный ключ билета должен иметь другое имя, например:

api/tickets/ticket_pk>/comments//

Django переход на страницу по primary key

Вообщем у меня есть страница с марками машин и мне нужно чтобы при клике на определенную марку меня перекидывало на страницу со всеми машинами этой марки. Все данные я в таблицы внес, почему-то на этапе перехода на страницу никак не могу правильно написать:

В файле car_detail.html у меня выводяться названия машин той или иной марки. Как мне правильно посылаться с файла cars.html чтобы открывать названия машин той или иной марки. Проект Называется cars и одно приложение которое там есть это car_marks

Отслеживать
задан 27 сен 2022 в 20:58
51 7 7 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Пойдём по порядку:

Создаем прокет

Думаю, тут сложностей не будет:

pip install django 
django-admin startapp CarShop . 
python manage.py startapp mainapp 

Добавляем приложение в список:

CarShop/settings.py

INSTALLED_APPS = [ . 'mainapp' ] 

Создаём модели

mainapp/models.py

from django.db import models class Mark(models.Model): # Название моделей принято писать в единственном числе name = models.CharField(max_length=64) # У марки должно быть имя (name), а не mark class Car(models.Model): # Для того, чтобы удобно обращаться к машинам марки (например mark.cars.all) нужно указать related_name mark = models.ForeignKey(Mark, on_delete=models.Case, related_name='cars') name = models.CharField(max_length=64) 
python manage.py makemigrations 
python manage.py migrate 

Заполняем базу данными. Для этого можно воспользоваться специальной консольной оболочкой django:

python manage.py shell 
>>> from mainapp.models import Mark, Car >>> >>> >>> Mark(name='mark1').save() >>> Mark(name='mark2').save() >>> Mark(name='mark3').save() >>> >>> >>> Car(mark_id=1, name='car1').save() >>> Car(mark_id=1, name='car2').save() >>> Car(mark_id=2, name='car3').save() >>> Car(mark_id=2, name='car4').save() >>> Car(mark_id=3, name='car5').save() >>> Car(mark_id=3, name='car6').save() 

Создаём urls

mainapp/urls.py

from django.urls import path from mainapp import views as mainapp app_name = 'mainapp' urlpatterns = [ path('marks/', mainapp.marks_list, name='mark_list'), # создаём ссылку на список марок path('marks/mark//', mainapp.mark_detail, name='mark_detail') # создаём ссылку на просмотр конкретной марки ] 

Подключаем его в корневом диспетчере url:

CarShop/urls.py

from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('mainapp.urls', namespace='main')) # Для удобства создаём namespace для приложения ] 

Создаём views

mainapp/views.py

from django.shortcuts import render from mainapp.models import Mark def marks_list(request): return render(request, 'mainapp/marks.html', ) def mark_detail(request, mark_id: int): return render(request, 'mainapp/mark_detail.html', ) # Получаем объект марки по id и передаем в шаблон 

Создаём шаблоны

Наши шаблоны должны храниться по такому пути: mainapp/templates/mainapp/ : Создаём mainapp/templates/mainapp/marks.html . В нём будет список всех марок

mainapp/templates/mainapp/marks.html

    Марки       /', mainapp.mark_detail, name='mark_detail') --> ">>  

Создаём mainapp/templates/mainapp/mark_detail.html . В нём будет описание и список машин марки

mainapp/templates/mainapp/mark_detail.html

Итоговая структура

Структура

Запускаем сервер

python manage.py runserver 0.0.0.0:8000 

Расширяем свое приложение

Мы уже выполнили часть необходимых шагов для создания веб-сайта: мы знаем как создать модель, URL, представление и шаблон. Мы также знаем, как улучшить визуальный дизайн с помощью CSS.

Время для практики!

Первое, что нам потребуется в блоге — страница для отображения конкретной записи, верно?

У нас уже есть модель Post , так что нам не нужно добавлять дополнительный код в файл models.py .

Создадим в шаблоне ссылку на страницу поста

Мы начнём с добавления ссылки внутри файла blog/templates/blog/post_list.html . Пока он выглядит следующим образом:

div class=«post»> div class=«date»> > div> h1>a href=«»>> a> h1> p>> p> div>

Нам хотелось бы иметь ссылку с заголовка поста в списке на страницу с подробной информацией о посте. Давай изменим

>

, чтобы получилась ссылка на пост:

h1>a href="">> a> h1> 

Самое время разобраться с загадочным . Как можешь предположить, синтаксис означает использование тегов шаблонов Django. На этот раз мы используем тот, что создаст для нас URL!

Параметр post_detail означает, что Django будет искать URL с именем post_detail в файле blog.urls.py .

А что насчёт pk=post.pk ? pk — это сокращение от primary key (первичный ключ). Он уникальным образом определяет каждую запись в базе данных. Поскольку мы не задали первичного ключа в нашей модели Post , Django создал такой ключ за нас (по умолчанию это порядковый номер, то есть 1, 2, 3…) и добавил поле pk к каждой записи блога. Для получения первичного ключа мы напишем post.pk — точно так же, как мы получали значения остальных полей ( title , author и т.д.) нашего объекта Post .

Теперь, когда мы перейдем по адресу http://127.0.0.1:8000/, мы получим ошибку (как и ожидается, поскольку у нас нет прописанного URL и представления для post_detail ). Она будет выглядеть следующим образом:

Ошибка NoReverseMatch

Создадим URL для страницы поста

Давай создадим в urls.py URL для представления post_detail !

Мы хотим, чтобы наш первый пост отображался на странице со следующим URL-адресом: http://127.0.0.1:8000/post/1/

Давай создадим URL в файле blog/urls.py и укажем Django на представление под названием post_detail , которое будет отображать пост целиком. Добавь строчку path(‘post//’, views.post_detail, name=’post_detail’) в файл blog/urls.py . Файл должен выглядеть так:

from django.urls import path from . import views urlpatterns = [ path('', views.post_list, name='post_list'), path('post//', views.post_detail, name='post_detail'), ] 

Фрагмент post// определяет шаблон URL-адреса. Сейчас мы его поясним:

  • post/ значит, что после начала строки URL должен содержать слово post и косую черту /. Пока всё в порядке.
  • — эта часть посложнее. Она означает, что Django ожидает целочисленное значение и преобразует его в представление — переменную pk .
  • / — затем нам нужен еще один символ / перед тем, как адрес закончится.

Славненько, мы добавили новый шаблон URL в файл blog/urls.py ! Давай обновим страницу: http://127.0.0.1:8000/. Бууум! Сервер снова перестал работать. Проверь консоль — как и ожидалось, ещё одна ошибка!

AttributeError

Помнишь, каким должен быть следующий шаг? Конечно: добавить представление!

Добавим представление для страницы поста

В этот раз представление получит дополнительный параметр pk . Но как дать нашему представлению знать о нём? Для этого мы определим функцию как def post_detail(request, pk): . Обрати внимание, что мы должны использовать то же имя переменной, что мы выбрали для обработки URL ( pk ). Пропуск переменной будет неправилен и приведёт к ошибке!

Теперь мы хотим получить одну конкретную запись из блога. Для этого потребуется использовать QuerySet:

Post.objects.get(pk=pk) 

Однако в этом коде есть проблема. Если не существует экземпляра объекта Post с заданным primary key ( pk ), мы получим страшную ошибку!

Ошибка DoesNotExist

Мы этого не хотим! Однако в Django, конечно, есть средство, которое позволит нам её обойти: get_object_or_404 . В случае, если не существует экземпляра объекта Post с заданным pk , мы получим намного более приятную страницу (которая называется Page Not Found 404 ).

Страница не найдена

Хорошая новость состоит в том, что ты можешь сделать свою страницу Page not found . Но для нас сейчас это не самая важная задача, и мы её пропустим.

Хорошо, пришло время добавить представление в файл views.py !

В файле blog/urls.py мы создали шаблон URL под названием post_detail , который ссылался на представление под названием views.post_detail . Это значит, что Django ожидает найти функцию-представление с названием post_detail в blog/views.py .

Нам нужно открыть файл blog/views.py и добавить в него следующий код:

from django.shortcuts import render, get_object_or_404 

— рядом с другими строками, начинающимися с from . В конец же файла мы добавим наше новое представление:

def post_detail(request, pk): post = get_object_or_404(Post, pk=pk) return render(request, 'blog/post_detail.html', 'post': post>) 

Вот так. Теперь обнови страницу http://127.0.0.1:8000/

Представление списка записей

Заработало! Только что произойдёт, если ты попробуешь перейти по ссылке из заголовка записи?

Ошибка TemplateDoesNotExist

Ой, нет! Другая ошибка! Но мы уже знаем, как иметь с ней дело, верно? Нам нужно добавить шаблон!

Создадим шаблон для страницы поста

Мы создадим файл post_detail.html в директории blog/templates/blog .

Он должен содержать следующее:

  div class="post"> div class="date"> > div> h1>> h1> p>> p> div> 

И снова мы расширяем base.html . В блоке content мы отображаем дату публикации (published_date, если она существует), заголовок и текст. Нам также нужно обсудить пару важных вещей, хорошо?

. — это тег шаблона, который мы можем использовать, если нам нужно что-то проверить (помнишь конструкцию if . else .. из главы Введение в Python?). В данном случае мы хотим проверить, не пуста ли дата публикации поста — published_date .

Отлично, можешь перезагрузить страницу и проверить, пропала ли ошибка Page not found .

Отдельная страницы записи

Ура! Всё работает!

Ещё одна вещь: развёртывание!

Было бы неплохо проверить, что веб-сайт всё ещё будет работать на PythonAnywhere, верно? Давай еще раз проведём развёртывание.

$ git status $ git add --all . $ git status $ git commit -m "Added view and template for detailed blog post as well as CSS for the site." $ git push 
$ cd ~/.pythonanywhere.com $ git pull [. ] 

И нажми Reload на вкладке Web.

Обновим статические файлы на сервере

Серверы вроде PythonAnywhere часто обрабатывают статические файлы (например, CSS) не так, как Python-файлы. Так происходит потому, что сервера могут оптимизировать их использование так, чтобы они быстрее загружались. В результате после того, как мы поменяли CSS-файлы, надо дать серверу команду обновить их. Эта команда называется collectstatic .

Начни с активации virtualenv, если окружение уже не активно (PythonAnywhere использует для этого команду workon . Она работает так же, как source myenv/bin/activate , которую ты используешь на своём компьютере.

$ workon .pythonanywhere.com (ola.pythonanywhere.com)$ python manage.py collectstatic [. ] 

Команда manage.py collectstatic немножко похожа на manage.py migrate . Мы сперва вносим какие-то изменения в наш код, а затем сообщаем Django применить эти изменения — к набору статических файлов на сервере или к базе данных.

В любом случае, мы теперь готовы перейти по ссылке «Web» page (нажав на кнопку в меню в правом верхнем углу консоли) и кликнуть на Reload, а затем посмотреть на страницу https://subdomain.pythonanywhere.com, где отобразится результат.

Вот и всё! Поздравляем 🙂

results matching » «

No results matching » «

PK в Django, при обновлении последних данных?

Всем привет! Помогите разобраться с PK. А именно, нужно сделать редактирование последних данных(meter_1-meter_5), для конкретного пользователя.
Заранее спасибо!

Model class AddMeterData(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) meter_1 = models.IntegerField() meter_2 = models.IntegerField() meter_3 = models.IntegerField() meter_4 = models.IntegerField() meter_5 = models.IntegerField() created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) view class MeterUpdateView(UpdateView): model = AddMeterData form_class = AddMeterForm template_name = 'add_meters/update.html' fields = ['meter_1', 'meter_2', 'meter_3', 'meter_4', 'meter_5'] success_url = reverse_lazy('meters:main') context_object_name = 'meter' def get_object(self, queryset=None): try: obj = AddMeterData.objects.filter(user=self.request.user).latest('created') return obj except AddMeterData.DoesNotExist: raise Http404('Meter data not found') except ValueError: raise Http404('Invalid meter data id') url path('/update/', MeterUpdateView.as_view(), name='update'), ссылка на template " >Update error NoReverseMatch at / Reverse for 'update' with arguments '('',)' not found. 1 pattern(s) tried: ['(?P[0-9]+)/update/\\Z']
  • Вопрос задан более года назад
  • 80 просмотров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *