πŸπŸš€ Django с нуля. Π§Π°ΡΡ‚ΡŒ 3: созданиС ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ΠΉ, сТатиС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, CRUD ΠΈ пагинация

Π’ Π·Π°ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ части Ρ‚ΡƒΡ‚ΠΎΡ€ΠΈΠ°Π»Π° разбСрСмся с автоматичСским созданиСм ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ΠΉ ΠΈ ΡƒΠΌΠ΅Π½ΡŒΡˆΠ΅Π½ΠΈΠ΅ΠΌ Π°Π²Π°Ρ‚Π°Ρ€ΠΎΠΊ, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ CRUD, ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ ΠΈΠ· json-Ρ„Π°ΠΉΠ»Π° ΠΈ сдСлаСм ΠΏΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΡŽ.
πŸπŸš€ Django с нуля. Π§Π°ΡΡ‚ΡŒ 3: созданиС ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ΠΉ, сТатиС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, CRUD ΠΈ пагинация

Π’Ρ€Π΅Ρ‚ΠΈΠΉ этап Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ

На этом этапС ΠΌΡ‹ займСмся профилями ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ ΠΈ прСдоставим Π°Π²Ρ‚ΠΎΡ€Π°ΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ, Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ свои записи со стороны Ρ„Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄Π°. Код для всСх Ρ„Π°ΠΉΠ»ΠΎΠ² этой части ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° находится здСсь.

Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ΠΉ

На ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΌ этапС ΠΌΡ‹ ΡƒΠΆΠ΅ создали модСль для профиля ΠΈ зарСгистрировали Π΅Π΅. Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π½ΡƒΠΆΠ½ΠΎ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ сохранСниС Π°Π²Π°Ρ‚Π°Ρ€ΠΎΠΊ Π² Π½ΡƒΠΆΠ½ΠΎΠΉ ΠΏΠ°ΠΏΠΊΠ΅. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Π”ΠΆΠ°Π½Π³ΠΎ создаСт ΠΏΠ°ΠΏΠΊΡƒ profile_pics (для хранСния Π°Π²Π°Ρ‚Π°Ρ€ΠΎΠΊ) Π½Π° ΠΎΠ΄Π½ΠΎΠΌ ΡƒΡ€ΠΎΠ²Π½Π΅ с ΠΏΠ°ΠΏΠΊΠ°ΠΌΠΈ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, Ρ‡Ρ‚ΠΎ Π½Π΅ слишком ΡƒΠ΄ΠΎΠ±Π½ΠΎ.

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ располоТСниС ΠΏΠ°ΠΏΠΊΠΈ, ΠΎΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅ my_site\settings.py ΠΈ Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π² Π½Π°Ρ‡Π°Π»ΠΎ Ρ„Π°ΠΉΠ»Π° import os, Π° Π² ΠΊΠΎΠ½Π΅Ρ† Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅:

        MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

    

ЗапуститС сСрвСр, Π²ΠΎΠΉΠ΄ΠΈΡ‚Π΅ Π² панСль управлСния – Ρ‚Π°ΠΌ ΡƒΠΆΠ΅ Π΅ΡΡ‚ΡŒ Ρ€Π°Π·Π΄Π΅Π» Profiles, ΠΏΡ€ΠΈΡ‡Π΅ΠΌ количСство ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ΠΉ Ρ€Π°Π²Π½ΠΎ 0, хотя ΠΌΡ‹ создали Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ. Π§ΡƒΡ‚ΡŒ ΠΏΠΎΠ·ΠΆΠ΅ ΠΌΡ‹ рассмотрим, ΠΊΠ°ΠΊ автоматичСски ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ с рСгистрациСй Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚ΠΎΠ², Π° ΠΏΠΎΠΊΠ° Ρ‡Ρ‚ΠΎ создадим Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ ΠΎΠ΄ΠΈΠ½ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒ для Π°Π΄ΠΌΠΈΠ½Π° с Π°Π²Π°Ρ‚Π°Ρ€ΠΊΠΎΠΉ, ΠΈ ΠΎΠ΄ΠΈΠ½ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒ для ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ Π±Π΅Π· Π°Π²Π°Ρ‚Π°Ρ€ΠΊΠΈ – Π²Π΅Ρ€Π½Π΅Π΅, Ρƒ Π½Π΅Π³ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π°Π²Π°Ρ‚Π°Ρ€ΠΊΠ° ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ default.jpg, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΈ ΠΏΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ Π² ΠΏΠ°ΠΏΠΊΡƒ media (Π½ΠΎ Π½Π΅ Π²Π½ΡƒΡ‚Ρ€ΡŒ profile_pics, Π° рядом).

ВнСситС измСнСния Π² шаблон профиля users\profile.html:

        {% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
	<div class="content-section">
  	<div class="media">
    	<img class="rounded-circle account-img" src="{{ user.profile.image.url }}">
    	<div class="media-body">
      	<h2 class="account-heading">{{ user.username }}</h2>
  	    <p class="text-secondary">{{ user.email }}</p>
    	</div>
  	</div>
  	<!-- Π—Π΄Π΅ΡΡŒ Π±ΡƒΠ΄Π΅Ρ‚ Ρ„ΠΎΡ€ΠΌΠ° -->
	</div>
{% endblock content %}

    

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒ Π°Π΄ΠΌΠΈΠ½Π° выглядит Ρ‚Π°ΠΊ:

Π’ ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ Π°Π΄ΠΌΠΈΠ½Π° появилась Π°Π²Π°Ρ‚Π°Ρ€ΠΊΠ°
Π’ ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ Π°Π΄ΠΌΠΈΠ½Π° появилась Π°Π²Π°Ρ‚Π°Ρ€ΠΊΠ°

АвтоматичСскоС созданиС ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ΠΉ

ΠžΡΡ‚Π°Π»ΠΎΡΡŒ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ Π·Π°Π΄Π°Ρ‡Ρƒ с автоматичСским созданиСм ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ΠΉ Π²ΠΎ врСмя рСгистрации. Π’ Π”ΠΆΠ°Π½Π³ΠΎ для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Ρ‚Π°ΠΊΠΎΠΉ Π»ΠΎΠ³ΠΈΠΊΠΈ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‚ сигналы. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Ρ„Π°ΠΉΠ» users\signals.py ΠΈ сохранитС Π² Π½Π΅ΠΌ этот ΠΊΠΎΠ΄. Π­Ρ‚ΠΈ сигналы Π½ΡƒΠΆΠ½ΠΎ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² users\apps.py.

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ автоматичСскоС созданиС ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ΠΉ – запустим сСрвСр ΠΈ создадим Π½ΠΎΠ²Ρ‹ΠΉ Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚. ВсС ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΎΡΡŒ:

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ автоматичСски
Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ автоматичСски
Π‘ΠΎΠ»ΡŒΡˆΠ΅ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° питониста»

Π—Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΡ„ΠΈΠ»Π΅ΠΉ

ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌ Π½ΡƒΠΆΠ½Π° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ Π²Π½ΠΎΡΠΈΡ‚ΡŒ измСнСния Π² ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒ – ΠΌΠ΅Π½ΡΡ‚ΡŒ Ρ„ΠΎΡ‚ΠΎ, Π½ΠΈΠΊ ΠΈ Π΅ΠΌΠ΅ΠΉΠ», Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€. Для этого внСсСм дополнСния Π² Ρ„Π°ΠΉΠ» users\forms.py – Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΈΠΌΠΏΠΎΡ€Ρ‚ from .models import Profile Π² Π½Π°Ρ‡Π°Π»ΠΎ ΠΈ этот ΠΊΠΎΠ΄ Π² ΠΊΠΎΠ½Π΅Ρ†:

        class UserUpdateForm(forms.ModelForm):
	email = forms.EmailField()
 
	class Meta:
    	model = User
    	fields = ['username', 'email']
 
 
class ProfileUpdateForm(forms.ModelForm):
	class Meta:
    	model = Profile
    	fields = ['image']

    

ΠŸΠ΅Ρ€Π΅ΠΉΠ΄Π΅ΠΌ ΠΊ users\views.py – Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ Ρ‚Π°ΠΊ. Π’ шаблон profile.html Ρ‚ΠΎΠΆΠ΅ Π½ΡƒΠΆΠ½ΠΎ внСсти дополнСния – Π²ΡΡ‚Π°Π²ΡŒΡ‚Π΅ этот ΠΊΠΎΠ΄ вмСсто коммСнтария "здСсь Π±ΡƒΠ΄Π΅Ρ‚ Ρ„ΠΎΡ€ΠΌΠ°":

           	<form method="POST" enctype="multipart/form-data">
      	{% csrf_token %}
      	<fieldset class="form-group">
          	<legend class="border-bottom mb-4">Π’Π°Ρˆ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒ</legend>
          	{{ u_form|crispy }}
              {{ p_form|crispy }}
      	</fieldset>
      	<div class="form-group">
          	<button class="btn btn-outline-info" type="submit">ΠžΠ±Π½ΠΎΠ²ΠΈΡ‚ΡŒ</button>
      	</div>
  	</form>
    

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ Π² своих профилях:

ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π½ΠΈΠΊ, Π΅ΠΌΠ΅ΠΉΠ» ΠΈ Π°Π²Π°Ρ‚Π°Ρ€
ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π½ΠΈΠΊ, Π΅ΠΌΠ΅ΠΉΠ» ΠΈ Π°Π²Π°Ρ‚Π°Ρ€

АвтоматичСскоС сТатиС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ

Если ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π·Π°Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ слишком большиС изобраТСния, сСрвСр скоро окаТСтся ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹ΠΌ. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ ΠΈΠΌΠ΅Π΅Ρ‚ смысл Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ автоматичСскоС сТатиС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Ρ… Π² качСствС Π°Π²Π°Ρ‚Π°Ρ€ΠΎΠΊ. Π’Π°ΠΊΡƒΡŽ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ прСдоставляСт Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Pillow, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΡ‹ ΡƒΠΆΠ΅ использовали. Для сТатия Ρ„ΠΎΡ‚ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Pillow Π² users\models.py Π½ΡƒΠΆΠ½ΠΎ ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ этот ΠΊΠΎΠ΄. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΊΡ€ΡƒΠΏΠ½Ρ‹Π΅ изобраТСния ΡƒΠΌΠ΅Π½ΡŒΡˆΠ°ΡŽΡ‚ΡΡ автоматичСски.

ΠžΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π°Π²Π°Ρ‚Π°Ρ€ΠΎΠΊ Π² постах

Пока Ρ‡Ρ‚ΠΎ изобраТСния ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ Π²ΠΈΠ΄Π½Ρ‹ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² ΠΈΡ… профилях. Π§Ρ‚ΠΎΠ±Ρ‹ Ρ„ΠΎΡ‚ΠΎ Π°Π²Ρ‚ΠΎΡ€ΠΎΠ² ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π»ΠΈΡΡŒ Π² постах Π±Π»ΠΎΠ³Π°, внСсСм дополнСния Π² шаблон blog\home.html – сохранитС Π² Π½Π΅ΠΌ этот ΠΊΠΎΠ΄. Аватарка ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ показываСтся Π² постС:

Аватарка Π°Π²Ρ‚ΠΎΡ€Π° отобраТаСтся рядом с Π΅Π³ΠΎ записями
Аватарка Π°Π²Ρ‚ΠΎΡ€Π° отобраТаСтся рядом с Π΅Π³ΠΎ записями

CRUD

Π§Ρ‚ΠΎΠ±Ρ‹ Π΄Π°Ρ‚ΡŒ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ постами, Π½ΡƒΠΆΠ½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ CRUD – Π½Π°Π±ΠΎΡ€ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ ΠΏΠΎ созданию, Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ ΠΈ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΡŽ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π°. Π‘ΠΎΠ·Π΄Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΡ‰Π΅, Ссли ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ ΠΎΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ прСдставлСния ΠΊ классам. Для этого Π½Ρ‹Π½Π΅ΡˆΠ½Π΅Π΅ содСрТимоС Ρ„Π°ΠΉΠ»Π° blog\views.py Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π½Π° это, Π° ΠΊΠΎΠ΄ blog\urls.py Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ Ρ‚Π°ΠΊ. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° классы PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView) ΠΈ PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView) – ΠΎΠ½ΠΈ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‚ созданиС, Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ записСй Ρ‚ΠΎΠ»ΡŒΠΊΠΎ зарСгистрированными ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌΠΈ; ΠΏΡ€ΠΈ этом Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ посты ΠΌΠΎΠ³ΡƒΡ‚ лишь ΠΈΡ… Π°Π²Ρ‚ΠΎΡ€Ρ‹.

Для просмотра ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… постов создадим шаблон post_detail.html Π²ΠΎΡ‚ с Ρ‚Π°ΠΊΠΈΠΌ ΠΊΠΎΠ΄ΠΎΠΌ. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ пост ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ: http://localhost:8000/post/1/. Π”ΠΎΠ±Π°Π²ΠΈΠΌ эту Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π² шаблон home.html:

        <h2><a class="article-title" href="{% url 'post-detail' post.id %}">{{ post.title }}</a></h2>
    

ΠŸΠ΅Ρ€Π΅ΠΉΠ΄Π΅ΠΌ ΠΊ ΡˆΠ°Π±Π»ΠΎΠ½Ρƒ создания Π½ΠΎΠ²Ρ‹Ρ… постов. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Ρ„Π°ΠΉΠ» post_form.html с Ρ‚Π°ΠΊΠΈΠΌ ΠΊΠΎΠ΄ΠΎΠΌ. Π€ΠΎΡ€ΠΌΠ° Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒΡΡ ΠΏΠΎ адрСсу http://localhost:8000/post/new/:

ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹Π΅ записи
ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹Π΅ записи

ПослС создания записи слСдуСт ΠΏΠ΅Ρ€Π΅Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ Π½Π° ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ страницу поста. Для этого ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚Π΅ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄ blog\models.py Π½Π° этот, ΠΈ всС Π·Π°Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚:

ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Π°Ρ страница для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ записи
ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Π°Ρ страница для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ записи

Записи ΡƒΠΆΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ, Π½ΠΎ ΠΏΠΎΠΊΠ° Ρ‡Ρ‚ΠΎ нСльзя ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ. Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ Π½ΡƒΠΆΠ½Ρ‹ΠΉ шаблон – Ρ„Π°ΠΉΠ» blog\post_confirm_delete.html. Код для Π½Π΅Π³ΠΎ Π΅ΡΡ‚ΡŒ здСсь. Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚, послС подтвСрТдСния удалСния запись исчСзаСт, Π° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ пСрСнаправляСтся Π½Π° Π³Π»Π°Π²Π½ΡƒΡŽ страницу Π±Π»ΠΎΠ³Π°:

ΠŸΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ удалСния
ΠŸΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ удалСния

ΠžΡΡ‚Π°Π»ΠΎΡΡŒ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ссылку Π½Π° созданиС Π½ΠΎΠ²ΠΎΠΉ записи Π½Π° панСль Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΠΈ – ΠΌΡ‹ сдСлаСм это Π² шаблонС base.html, Π΄ΠΎΠ±Π°Π²ΠΈΠ² всСго ΠΎΠ΄Π½Ρƒ строку <a class="nav-item nav-link" href="{% url 'post-create' %}">Новая запись</a>. ВсС Π³ΠΎΡ‚ΠΎΠ²ΠΎ! Если Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚, ΡΠ²Π΅Ρ€ΡŒΡ‚Π΅ΡΡŒ с Π³ΠΎΡ‚ΠΎΠ²Ρ‹ΠΌ ΠΊΠΎΠ΄ΠΎΠΌ ΠΊ Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΌΡƒ этапу.

Π§Π΅Ρ‚Π²Π΅Ρ€Ρ‚Ρ‹ΠΉ этап Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ

На Π·Π°ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΌ этапС Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π½Π°Π΄ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠΌ ΠΌΡ‹ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΠΌ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ ΠΈΠ· json Ρ„Π°ΠΉΠ»Π° (с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠΉ консоли Django), сдСлаСм ΠΏΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΡŽ ΠΈ обСспСчим Π²Ρ‹Π²ΠΎΠ΄ всСх постов Π°Π²Ρ‚ΠΎΡ€Π° Π½Π° ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ страницС.

Π˜ΠΌΠΏΠΎΡ€Ρ‚ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° ΠΈΠ· Ρ„Π°ΠΉΠ»Π° json

Π‘ΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ посты ΠΎΡ‚ ΠΈΠΌΠ΅Π½ΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Π°Π²Ρ‚ΠΎΡ€ΠΎΠ² ΡƒΡ‚ΠΎΠΌΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ, поэтому ΠΌΡ‹ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΎΠΉ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° ΠΈΠ· Π³ΠΎΡ‚ΠΎΠ²ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° posts.json. Запустим ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΡƒΡŽ консоль Π”ΠΆΠ°Π½Π³ΠΎ python manage.py shell ΠΈ ΠΏΡ€ΠΎΠ²Π΅Π΄Π΅ΠΌ ΠΈΠΌΠΏΠΎΡ€Ρ‚. ΠžΡ‚ΡΡ‚ΡƒΠΏΡ‹ Π² консоли – 2 вмСсто ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹Ρ… 4:

        >>> import json
>>> from blog.models import Post
>>> with open('posts.json', encoding="utf8") as f:
...   posts_json = json.load(f)
...
>>> for post in posts_json:
...   post = Post(title=post['title']), content=post['content'], author_id=post['user_id']
...   post.save()
...
>>> exit()

    

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π½Π° нашСй Π³Π»Π°Π²Π½ΠΎΠΉ страницС отобраТаСтся мноТСство записСй.

ΠŸΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΡ

ΠŸΠΎΡ€Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΡŽ – Ρ€Π°Π·Π±ΠΈΠ΅Π½ΠΈΠ΅ постов Π½Π° страницы. Для раздСлСния постов Π½Π° страницы внСсСм измСнСния Π² класс PostListView(ListView) Π² Ρ„Π°ΠΉΠ»Π΅ blog\views.py – Π΄ΠΎΠ±Π°Π²ΠΈΠΌ строку paginate_by = 5. ΠžΡ‚Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΡƒΠ΅ΠΌ шаблон home.html – размСстим Π»ΠΎΠ³ΠΈΠΊΡƒ ΠΏΠ°Π³ΠΈΠ½Π°Ρ‚ΠΎΡ€Π° ΠΌΠ΅ΠΆΠ΄Ρƒ {% end for %} ΠΈ {% end block content%} Π² ΠΊΠΎΠ½Ρ†Π΅ Ρ„Π°ΠΉΠ»Π°. Записи Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Ρ‹ Π½Π° страницы:

ΠŸΠ°Π³ΠΈΠ½Π°Ρ‚ΠΎΡ€ раздСляСт записи ΠΏΠΎ 5 постов Π½Π° страницС
ΠŸΠ°Π³ΠΈΠ½Π°Ρ‚ΠΎΡ€ раздСляСт записи ΠΏΠΎ 5 постов Π½Π° страницС

Π•Ρ‰Π΅ Π±Ρ‹Π»ΠΎ Π±Ρ‹ Π·Π΄ΠΎΡ€ΠΎΠ²ΠΎ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ Π½Π° страницС ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ всС записи, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠ½ создал – с ΠΏΠ°Π³ΠΈΠ½Π°Ρ†ΠΈΠ΅ΠΉ, Ссли записСй ΠΌΠ½ΠΎΠ³ΠΎ. Для этого ΠΌΡ‹ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π² blog\views.py ΠΈΠΌΠΏΠΎΡ€Ρ‚ get_object_or_404 ΠΈ Π½ΠΎΠ²Ρ‹ΠΉ класс:

        class UserPostListView(ListView):
	model = Post
	template_name = 'blog/user_posts.html'  # <app>/<model>_<viewtype>.html
	context_object_name = 'posts'
	paginate_by = 5
 
	def get_queryset(self):
    	user = get_object_or_404(User, username=self.kwargs.get('username'))
    	return Post.objects.filter(author=user).order_by('-date_posted')

    

Π‘Π΄Π΅Π»Π°Π΅ΠΌ шаблон user_posts.html ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π½ΠΎΠ²Ρ‹ΠΉ ΠΏΡƒΡ‚ΡŒ Π² Ρ„Π°ΠΉΠ»Π΅ blog\urls.py:

        path('user/<str:username>', UserPostListView.as_view(), name='user-posts').
    

ΠžΡΡ‚Π°Π»ΠΎΡΡŒ внСсти ΠΏΠΎΠΏΡ€Π°Π²ΠΊΡƒ Π² Π΄Π°Π½Π½Ρ‹Π΅ Π°Π²Ρ‚ΠΎΡ€Π° Π² шаблон home.html:

        <a class="mr-2" href="{% url 'user-posts' post.author.username %}">{{ post.author }}</a>
    

ΠΈ Π² post_detail.html:

        <a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{ object.author }}</a>.
    

И всС Π·Π°Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΎ:

Записи ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ выводятся Π½Π° Π΅Π³ΠΎ Π»ΠΈΡ‡Π½ΠΎΠΉ страницС
Записи ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ выводятся Π½Π° Π΅Π³ΠΎ Π»ΠΈΡ‡Π½ΠΎΠΉ страницС

Π’Π΅ΡΡŒ ΠΊΠΎΠ΄ для Ρ‡Π΅Ρ‚Π²Π΅Ρ€Ρ‚ΠΎΠ³ΠΎ этапа ΠΌΠΎΠΆΠ½ΠΎ Π²Π·ΡΡ‚ΡŒ здСсь.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

ΠŸΠΎΡΡ‚Π°ΠΏΠ½ΠΎΠ΅ созданиС простого Π²Π΅Π±-прилоТСния Π΄Π°Π΅Ρ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ быстро ΠΎΡΠ²ΠΎΠΈΡ‚ΡŒ основныС ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π² Django. Π€Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ позволяСт достаточно просто Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠ»ΠΎΠΆΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ – Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, CRUD, – Π° ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΏΠΎΠΌΠΎΠ³Π°ΡŽΡ‚ Ρ€Π°Π·Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Ρ„ΠΎΡ€ΠΌΡ‹ ΠΈ автоматичСски ΡΠΆΠΈΠΌΠ°Ρ‚ΡŒ изобраТСния. НапоминаСм, Ρ‡Ρ‚ΠΎ ΠΊΠΎΠ΄ для всСх этапов ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° доступСн здСсь.

***

ΠœΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹ ΠΏΠΎ Ρ‚Π΅ΠΌΠ΅


ΠœΠ•Π ΠžΠŸΠ Π˜Π―Π’Π˜Π―

ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ

Π’ΠΠšΠΠΠ‘Π˜Π˜

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ вакансию

Π›Π£Π§Π¨Π˜Π• БВАВЬИ ПО Π’Π•ΠœΠ•