ساخت یه شبکه نیمه‌اجتماعی و کاستومایز شده:))))

وضعیت
موضوع بسته شده است.
  • شروع کننده موضوع
  • مدیر
  • #1

ememlia

⁦(⊙_◎)⁩
عضو مدیران انجمن
ارسال‌ها
856
امتیاز
19,972
نام مرکز سمپاد
شهید بهشتی
شهر
.
سال فارغ التحصیلی
1397
عنوان نوشتن از قسمت‌های سختشه:)‌))


نمیدونم کیوتاک رو یادتونه یا نه:)‌))‌ شخصا خیلی تلاش کردم فراموش کنم اون کدهای آشغالی که نوشتمو:‌)))
آخرش هم اگه یادتونه باشه بخاطر اپتیمایز نبودنش کل داستان رو بستم به امید اینکه فراموش بشه:)
این تاپیک ادامه همون تاپیکه ولی نمیدونم بخوام خروجیش ادامه قبلیه باشه یا نه
راستش اصن ایده ای ندارم قراره چی بشه :rolleyes: :)‌)

داشتم فکر میکردم یه پروژه جنگو تو گیتم داشته باشم که از وبلاگ و اینا یکم باحال‌تر باشه و ایده‌ای نداشتم
چندهفته پیشا با بچه ها داشتیم راجب کیوتاک میگفتیم و بعدش از شبکه اجتماعی ایده‌آلمون حرف زدیم این ایده اومد چیزی که میخوایم رو بسازیم:)‌))
همین‌قدر ساده:)

۱.گوگل هیچ قسمتی از حرفامون رو ایندکس نکنه
۲.برای عضویت تنها به یوزرنیم و پس‌ورد نیاز باشه و هرکسی بتونه ناشناس بمونه
۳.افراد برای عضو شدن احتیاج دارن ازطرف یکی از یوزرها اینوایت بشن
۴.هر یوزری پروفایل خودشو داره که میتونه اونجا حرف بزنه و بقیه میتونن فالوش کنن
۵.امکان بلاک کردن و ایگنور کردن باشه
۶.یه سکشن جدا داشته باشیم که بشه ناشناس پست گذاشت
۷.نویسنده بتونه امکان امتیاز دادن به پستش رو فعال یا غیرفعال کنه
۸.برای پست ها بشه کامنت گذاشت و برای کامنت ها هم بشه کامنت گذاشت:)‌)))
۹.امکان ریست اکانت با یوزرنیم جدید
۱۰.سین هایی که پستات میخوره رو ببینی
۱۱.ارسال پیام ناشناس به هر اکانت
۱۲. پ.خ بزنین بگین فیچر مدنظر شما چیه:)‌)))
این لیست آپدیت میشه.

هدف خاصی وجود نداره(البته اکانت گیت‌هابم رو ریست کردم ... پر کردن اونم یه هدفه:-) ) ... احتمالا ۲۰-۳۰ نفر میشیم یه مدت حرف میزنیم همین:‌))

۱.پایتون
۲.جنگو
۳.گیت
۴.داکر
۵.جی‌اس
۶.بوت‌استرپ
۷.پستگرس کیوال
۸.جی‌کوئری
۹. ....
 
  • شروع کننده موضوع
  • مدیر
  • #2

ememlia

⁦(⊙_◎)⁩
عضو مدیران انجمن
ارسال‌ها
856
امتیاز
19,972
نام مرکز سمپاد
شهید بهشتی
شهر
.
سال فارغ التحصیلی
1397
قسمت صفر -> جنگو

فریمورک وب یک چارچوب نرم افزاری هست که برای آسان تر کردن فرآیند توسعه وب استفاده میشه. فریمورک ها باعث میشن تا شما چرخ رو دوباره اختراع نکنید
در واقع وب‌فریمورک‌ مجموعه‌ای از کتاب‌خانه‌هاست (Library) که نیاز برنامه‌نویس را برای انجام کارهای تکراری به حداقل می‌رساند. به طور کلی وب‌فریمورک‌ها شامل فریمورک‌های فرانت‌اند و فریمورک‌های بک‌اند می‌شوند. فریمورک‌های فرانت‌اند برای پیاده‌سازی کد‌های سمت کاربر استفاده می‌شوند و عمدتاً از تکنولوژی‌هایی مثل javascript ،css و html در آن‌ها استفاده می‌شود. اما فریمورک‌های بک‌اند برای پیاده‌سازی کدهای سمت سرور استفاده می‌شوند که کاربران قادر به دیدن آن‌ها نیستند.
جنگو یا Django، فریمورکی بسیار محبوب و همچنان با وجود بلوغ کافی، رو به رشد است که با زبان پایتون پیاده‌سازی شده و جامعه‌ای به شدت فعال و پویا دارد
منبع:کوئرا


تمامی وب‌اپ‌ها از ابتدا توسط شخص توسعه‌دهنده پیاده‌سازی می‌شد. از معایب این روش می‌توان به موارد زیر اشاره کرد:


  • زمان زیادی صرف زدن کدهایی می‌شد که تقریبا در همه‌ی وب‌اپ‌ها مشترک بودند.
  • توسعه اپ توسط عده‌ای خاص، کار را برای توسعه‌دهندگان آینده دشوار می‌کرد.
  • احتمال وجود باگ به خصوص باگ‌های امنیتی بالا می‌رفت.

اما ظهور وب‌فریمورک‌ها پاسخی شد برای تمام معایب ذکر شده‌:


  • اکنون بخش‌های مشترک وب‌اپ‌ها بصورت پکیج‌های آماده در هنگام توسعه در دسترس توسعه‌دهندگان هستند.
  • با وجود فریمورک‌ها ساختار پروژه حتی برای توسعه‌دهندگانی که در آینده به پروژه می‌پیوندند قابل درک‌تر خواهد‌بود.
  • در فریمورک‌ها تا میزان خوبی برای پیش‌گیری از به‌وجود آمدن باگ‌ها، راه‌حل‌های مطمئن درنظر گرفته شده است.
منبع:کوئرا
یه محیط مجازی درست کنیم که بتونیم ماژول هارو بهتر مدیریت کنیم:
اگه venv رو نصب نکردین:
کد:
sudo pip3 install virtualenv
بعد ساخت یه محیط مجازی:
کد:
python3 -m venv .venv
نهایتا فعال کردنش:
کد:
source .venv/bin/activate
حالا نصب جنگو:
کد:
pip install django

کد:
django-admin startproject config .
راجب انتخاب اسم پروژه و اون دات راه‌های زیادی هست ... این روش تو کتاب جنگو ویلیام وینسنت بود که خوشم ازش اومد
میشه پروژه رو ران کرد ببینیم چطوریاس:
کد:
pyhton manage.py runserver
اگه با مرورگر آدرس localhost:8000 رو باز کنین اینو میبینین:
django-configuration-with-apache-web-server1.png


ساختار پروژه هم همچینی چیزیه الان:


django-project2.png

به مرور قراره شلوغ بشه اینجا
معمولا یه پروژه خالی تو گیت درست میکنم و بعد کلون میکنم رو کامپیوترم و فایل های اولیم رو روش میریزم
کد:
git clone git@github.com:kavehmoradian/Qtalk.git
cd Qtalk
mv ../project/* .
rm ../project
git add -A
git commit -m "initial commit"
git push
لینک گیت‌هاب پروژه: https://github.com/kavehmoradian/Qtalk
یه اشتباه امنیتی کردم اینجا که یکم دیگه درستش میکنم:)‌))
 
  • شروع کننده موضوع
  • مدیر
  • #3

ememlia

⁦(⊙_◎)⁩
عضو مدیران انجمن
ارسال‌ها
856
امتیاز
19,972
نام مرکز سمپاد
شهید بهشتی
شهر
.
سال فارغ التحصیلی
1397
یه اشتباه امنیتی کردم اینجا که یکم دیگه درستش میکنم:)‌))
قضیه چیه؟
توی دایرکتوری کانفیگ و فایل ستینگز یه متغیر هست به اسم سیکرت‌کی
جاهای مختلفی استفاده میشه همونطور که از اسمش معلومه باید مخفی باشه
ولی ما چیکار کردیم؟ گذاشتیمش رو اینترنت همه ببیننش:‌))
واسه مخفی کردن داستان راه های مختلفی هست من از ماژول dotenv استفاده میکنم:

کد:
pip install python-dotenv
touch .env
vi .env

توی فایل .env متغیر سیکرت رو تعریف میکنم:
کد:
SECRET_KEY = 'django-insecure-mz&7ulfk$!8+#m_ppt*ra^=5z_dwp+9+yb(@*a)q!ufo-26x8-'
و به گیت‌ایگنور .env رو اضافه میکنم

حالا نوبت فایل ستینگز :
Python:
import os
from pathlib import Path
import dotenv
BASE_DIR = Path(__file__).resolve().parent.parent
dotenv_file = os.path.join(BASE_DIR, ".env")
if os.path.isfile(dotenv_file):
    dotenv.load_dotenv(dotenv_file)
   
SECRET_KEY = os.environ['SECRET_KEY']

الان میشه سیکرت‌کی رو عوض کنیم
requirements.txt رو هم درست کنیم:
کد:
pip freeze > requirements.txt

گیت:
کد:
git add -A
git commit -m 'put secret_key in .env'
git push
 
  • شروع کننده موضوع
  • مدیر
  • #4

ememlia

⁦(⊙_◎)⁩
عضو مدیران انجمن
ارسال‌ها
856
امتیاز
19,972
نام مرکز سمپاد
شهید بهشتی
شهر
.
سال فارغ التحصیلی
1397
حقیقتا نزدیک نتایج حوصله‌اش نیست:)‌)

میخوام فعلا یوزر هارو درست کنم امروز، بعدا ویو های مربوط به لاگین و رجیستر هم مینویسم

فلسفه داستان اینه که یوزرها بتونن ناشناس باشن و اطلاعات خاصی برای ثبت‌نام لازم نباشه بدن، پس لازم نیست براشون ایمیل تعریف کنم
ازونور اینکه ایمیل یا شماره تلفن نمیدن باعث میشه نتونم ایمیل بازیابی رمزعبور براشون بفرستم که عیب نداره، موقع ثبت‌نام هشدار میدم که رمز رو یگوشه بنویسید گم نشه:)‌)))

جنگو خودش کلاس یوزر پیشفرض خودش رو داره که ایمیل و یوزرنیم و اسم و ... رو ذخیره میکنه
به دو روش هم میشه اون یوزر پیشفرض جنگو رو گسترش داد ولی من تصمیم گرفتم کلا کلاس یوزر خودمو از اول تعریف کنم

نمیدونم بالا گفتم یا نه ولی هر پروژه جنگو از یسری app کوچیک درست شدن که کنار هم‌دیگه میشن کل پروژه
structure_drawing2_new.png

تا این لحظه هیچ اپی نساختیم، اسم اولین اپی که میسازم رو accounts میزارم تا قسمت مربوط به یوزرهارو اونجا هندل کنم:
کد:
source venv/bin/activate
python manage.py startapp accounts
یه همچین دایرکتوری ای به پروژه اضافه میشه:


توی ستینگ پروژه این اپ رو باید نصب کرد، درواقع باید کلاس کانفیگ اپ رو به پروژه معرفی کنیم:

Python:
INSTALLED_APPS = [
    #....
    'accounts.apps.AccountsConfig',
]
تا داریم تو همون فایل ستینگ میچرخیم بیاین به جنگو بگیم که یوزر پروژه رو خودمون قراره تعریف کنیم و از یوزر خودش استفاده نکنه:
Python:
AUTH_USER_MODEL = 'accounts.User'

توی اپ اکانتس تو فایل مدل‌ها یوزر رو تعریف میکنم:
Python:
from django.contrib.auth.models import AbstractBaseUser
from django.db import models
from .manager import UserManager
# منیجر رو بعدا قراره بسازیم

class User(AbstractBaseUser):
    username = models.CharField(
            verbose_name='UserName',
            max_length=25,
            unique=True,
    )
    avatar = models.ImageField(default='default.jpg', upload_to='profile_pics')
    is_active = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)
    bio = models.CharField(max_length=500, null=True, blank=True)
    sign = models.CharField(max_length=500, null=True, blank=True)
    created = models.DateTimeField(auto_now_add=True)

    objects = UserManager()
    # منیجر رو بعدا قراره بسازیم

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = []

    def __str__(self):
        return self.username

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

    @property
    def is_staff(self):
        return self.is_admin
همه یوزرهای کاستوم باید از کلاس AbstractBaseUser یوزر ارث بری کنن
برای یوزرها فیلدهای:
یوزرنیم
آواتار
فعال بودن
ادمین بودن
بیو
امضا
و تاریخ ساخت اکانت تعریف کردم
پسورد خیلی بدیهیه و چون بشکل خام ذخیره نمیشه لازم نیست تعریف بشه و تو کلاس پدر هست خودش
دوتا متود قبل از is_staff رو فعلا استفاده نکردم و همه مجوز هارو به همه دادم
و تو متود آخر گفتم هرکی ادمین باشه استف هم هست
منیجر این مدل رو مینویسیم حالا:
میشه تو همین فایل مدل‌ها نوشتش ولی نمیخوام شلوغش کنم و فایل manager.py رو مینویسم:
Python:
class UserManager(BaseUserManager):
    def create_user(self, username, password=None):
        if not username:
            raise ValueError('username required:)')

        user = self.model(username=username)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, password=None):
        if not username:
            raise ValueError('username required:)')

        user = self.create_user(
                username=username,
                password=password,
        )
        user.is_admin = True
        user.is_active = True
        user.save(using=self._db)
        return user
منیجرمون هم از بیس‌یوزرمنیجر ارث‌بری میکنه
دوتا متود میخواد یکی برای ساخت یوزر جدید و یکی برای ساخت یوزر ادمین
بعدا چیزای دیگه هم میشه اضافه کرد

اگه تو کد مدل دیده باشین is_active پیشفرض همه شی‌هارو false گذاشتم و معنیش اینه که کاربرها بعد از ثبت‌نام غیرفعال هستن:‌))
پس چطوری قراره یوزر رجیستر کنه؟ یا باید دستی تو پنل ادمین فعالش کنم یا باید کد دعوت داشته باشه:)‌))

گفتم ویوهای رجیستر و لاگین رو بعدا مینویسم ولی الان میخوام بتونم توی پنل ادمین یوزرهارو مدیریت کنم
فعلا بریم چنتا فرم بنویسیم واسه یوزرا:
فایلی به اسم forms.py میسازم

Python:
class UserCreationForm(forms.ModelForm):
    password1 = forms.CharField(label='password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='password confirmation',
                                widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ('username', )

    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise ValidationError("Passwords don't match")
        return password2

    def save(self, commit=True):
        user = super().save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user
یه فرم ساختم برای ساخت یوزر جدید
کلا ۳ تا فیلده و پسورد و تایید پسورد همینجا ولیدیت میشن
متود سیو این مدل‌فرم رو هم اوررایت کردم که پسورد هم باهاش سیو کنم
Python:
class UserChangeForm(forms.ModelForm):
    password = ReadOnlyPasswordHashField()

    class Meta:
        model = User
        fields = (‌'__all__')
یه فرم هم برای ویرایش ساختم که همه فیلد هارو داشته باشه

جنگو خودش یه ادمین پنل پیش‌فرض داره که میشه کاستومش کرد
فعلا از همون استفاده میکنم:

کد:
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .forms import UserCreationForm, UserChangeForm
from .models import User


class UserAdmin(BaseUserAdmin):
    form = UserChangeForm
    add_form = UserCreationForm

    list_display = ('username', 'is_active', 'is_admin')
    list_filter = ('is_active',)
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        ('Personal info', {'fields': ('avatar', 'bio', 'sign')}),
        ('Permissions', {'fields': ('is_admin', 'is_active')}),
    )

    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2'),
        }),
    )
    search_fields = ('username',)
    ordering = ('created',)
    filter_horizontal = ()

admin.site.register(User, UserAdmin)
admin.site.unregister(Group)

این فعلا ظاهر اوکی‌ای میده بعدا شاید تغیراتی دادم
این باید کار کنه فقط قبلش:
نشون دادن فایلای استاتیک وظیفه جنگو نیست، وظیفه وب‌سروره
فعلا که خبری از دیپلوی و وب‌سرور درست حسابی نیست بخاطر همین این قسمت رو هم به جنگو میدم:
توی ستینگ مدیاروت و مدیا یو آر ال رو مشخص میکنم:
Python:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
به url های استاتیک رو هم به url های پروژه اضافه میکنم:

کد:
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
این شرط باعث میشه اگه پسفردا دیپلوی کردیم لازم نباشه url هارو تغییر بدیم

هرکاری که تا الان کردیم رو باید به دیتابیس اضافه کنیم و بعد یه یوزر جدید بسازیم:
کد:
python manage.py check
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver 8000
رو پورت ۸۰۰۰ پروژه بالا اومده و میتونیم با ادمین پنل یکم بازی کنیم:






خلاصه اره دیگه
همین:)‌))
 
وضعیت
موضوع بسته شده است.
بالا