IyMg2YXYtNix2YjYuSBEamFuZ28g2YTZhdmI2YLYuSDYudix2LYg2KPZgdmE2KfZhSDZhdi5INiq2LPYrNmK2YQg2K/YrtmI2YQg2YjZhNmI2K3YqSDYqtit2YPZhSDZiNiq2KrYqNi5INiy2YjYp9ixCgojIDEuINil2LnYr9in2K8g2KfZhNmF2LTYsdmI2LkgKNmK2YXZg9mG2YMg2KrYrti32Yog2YfYsNinINil2YYg2YPZhtiqINij2YbYtNij2Kog2KfZhNmF2LTYsdmI2Lkg2KjYp9mE2YHYudmEKQojIGRqYW5nby1hZG1pbiBzdGFydHByb2plY3QgbW92aWVzaXRlCiMgY2QgbW92aWVzaXRlCiMgcHl0aG9uIG1hbmFnZS5weSBzdGFydGFwcCBjb3JlCgojIDIuIG1vZGVscy5weSAo2YHZiiDYqti32KjZitmCIGNvcmUpCmZyb20gZGphbmdvLmRiIGltcG9ydCBtb2RlbHMKZnJvbSBkamFuZ28uY29udHJpYi5hdXRoLm1vZGVscyBpbXBvcnQgVXNlcgoKY2xhc3MgTW92aWUobW9kZWxzLk1vZGVsKToKICAgIHRpdGxlID0gbW9kZWxzLkNoYXJGaWVsZChtYXhfbGVuZ3RoPTIwMCkKICAgIGRlc2NyaXB0aW9uID0gbW9kZWxzLlRleHRGaWVsZCgpCiAgICBwb3N0ZXIgPSBtb2RlbHMuSW1hZ2VGaWVsZCh1cGxvYWRfdG89J3Bvc3RlcnMvJykKICAgIHZpZGVvX3VybCA9IG1vZGVscy5VUkxGaWVsZCgpCiAgICBjcmVhdGVkX2F0ID0gbW9kZWxzLkRhdGVUaW1lRmllbGQoYXV0b19ub3dfYWRkPVRydWUpCgogICAgZGVmIF9fc3RyX18oc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYudGl0bGUKCmNsYXNzIFZpc2l0KG1vZGVscy5Nb2RlbCk6CiAgICBpcCA9IG1vZGVscy5HZW5lcmljSVBBZGRyZXNzRmllbGQoKQogICAgdGltZXN0YW1wID0gbW9kZWxzLkRhdGVUaW1lRmllbGQoYXV0b19ub3dfYWRkPVRydWUpCiAgICB1c2VyX2FnZW50ID0gbW9kZWxzLlRleHRGaWVsZCgpCiAgICBwYXRoID0gbW9kZWxzLkNoYXJGaWVsZChtYXhfbGVuZ3RoPTI1NSkKICAgIHJlZmVycmVyID0gbW9kZWxzLlRleHRGaWVsZChibGFuaz1UcnVlLCBudWxsPVRydWUpCgojIDMuIGFkbWluLnB5CmZyb20gZGphbmdvLmNvbnRyaWIgaW1wb3J0IGFkbWluCmZyb20gLm1vZGVscyBpbXBvcnQgTW92aWUsIFZpc2l0CgphZG1pbi5zaXRlLnJlZ2lzdGVyKE1vdmllKQphZG1pbi5zaXRlLnJlZ2lzdGVyKFZpc2l0KQoKIyA0LiBtaWRkbGV3YXJlLnB5ICjYr9in2K7ZhCBjb3JlKQpmcm9tIC5tb2RlbHMgaW1wb3J0IFZpc2l0CgpjbGFzcyBWaXNpdFRyYWNraW5nTWlkZGxld2FyZToKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBnZXRfcmVzcG9uc2UpOgogICAgICAgIHNlbGYuZ2V0X3Jlc3BvbnNlID0gZ2V0X3Jlc3BvbnNlCgogICAgZGVmIF9fY2FsbF9fKHNlbGYsIHJlcXVlc3QpOgogICAgICAgIHJlc3BvbnNlID0gc2VsZi5nZXRfcmVzcG9uc2UocmVxdWVzdCkKCiAgICAgICAgaXAgPSByZXF1ZXN0Lk1FVEEuZ2V0KCdSRU1PVEVfQUREUicpCiAgICAgICAgdXNlcl9hZ2VudCA9IHJlcXVlc3QuTUVUQS5nZXQoJ0hUVFBfVVNFUl9BR0VOVCcsICcnKQogICAgICAgIHJlZmVycmVyID0gcmVxdWVzdC5NRVRBLmdldCgnSFRUUF9SRUZFUkVSJywgJycpCiAgICAgICAgcGF0aCA9IHJlcXVlc3QucGF0aAoKICAgICAgICBWaXNpdC5vYmplY3RzLmNyZWF0ZSgKICAgICAgICAgICAgaXA9aXAsCiAgICAgICAgICAgIHVzZXJfYWdlbnQ9dXNlcl9hZ2VudCwKICAgICAgICAgICAgcGF0aD1wYXRoLAogICAgICAgICAgICByZWZlcnJlcj1yZWZlcnJlcgogICAgICAgICkKICAgICAgICByZXR1cm4gcmVzcG9uc2UKCiMgNS4gc2V0dGluZ3MucHkgLSDYo9i22YEg2KfZhNiq2KfZhNmKOgojINmB2YogTUlERExFV0FSRToKIyAnY29yZS5taWRkbGV3YXJlLlZpc2l0VHJhY2tpbmdNaWRkbGV3YXJlJywKCiMg2YHZiiBJTlNUQUxMRURfQVBQUzoKIyAnY29yZScsCgojIDYuIHVybHMucHkgKNmB2YogbW92aWVzaXRlL3VybHMucHkpCmZyb20gZGphbmdvLmNvbnRyaWIgaW1wb3J0IGFkbWluCmZyb20gZGphbmdvLnVybHMgaW1wb3J0IHBhdGgsIGluY2x1ZGUKZnJvbSBjb3JlIGltcG9ydCB2aWV3cwpmcm9tIGRqYW5nby5jb25mIGltcG9ydCBzZXR0aW5ncwpmcm9tIGRqYW5nby5jb25mLnVybHMuc3RhdGljIGltcG9ydCBzdGF0aWMKCnVybHBhdHRlcm5zID0gWwogICAgcGF0aCgnYWRtaW4vJywgYWRtaW4uc2l0ZS51cmxzKSwKICAgIHBhdGgoJycsIHZpZXdzLm1vdmllX2xpc3QsIG5hbWU9J21vdmllX2xpc3QnKSwKICAgIHBhdGgoJ2xvZ2luLycsIHZpZXdzLmxvZ2luX3ZpZXcsIG5hbWU9J2xvZ2luJyksCiAgICBwYXRoKCdkYXNoYm9hcmQvJywgdmlld3MuZGFzaGJvYXJkLCBuYW1lPSdkYXNoYm9hcmQnKSwKXSArIHN0YXRpYyhzZXR0aW5ncy5NRURJQV9VUkwsIGRvY3VtZW50X3Jvb3Q9c2V0dGluZ3MuTUVESUFfUk9PVCkKCiMgNy4gdmlld3MucHkgKGNvcmUpCmZyb20gZGphbmdvLnNob3J0Y3V0cyBpbXBvcnQgcmVuZGVyLCByZWRpcmVjdApmcm9tIGRqYW5nby5jb250cmliLmF1dGggaW1wb3J0IGF1dGhlbnRpY2F0ZSwgbG9naW4KZnJvbSBkamFuZ28uY29udHJpYi5hdXRoLmRlY29yYXRvcnMgaW1wb3J0IGxvZ2luX3JlcXVpcmVkCmZyb20gLm1vZGVscyBpbXBvcnQgTW92aWUKCgpkZWYgbW92aWVfbGlzdChyZXF1ZXN0KToKICAgIG1vdmllcyA9IE1vdmllLm9iamVjdHMuYWxsKCkKICAgIHJldHVybiByZW5kZXIocmVxdWVzdCwgJ21vdmllX2xpc3QuaHRtbCcsIHsnbW92aWVzJzogbW92aWVzfSkKCgpkZWYgbG9naW5fdmlldyhyZXF1ZXN0KToKICAgIGlmIHJlcXVlc3QubWV0aG9kID09ICdQT1NUJzoKICAgICAgICB1c2VybmFtZSA9IHJlcXVlc3QuUE9TVFsndXNlcm5hbWUnXQogICAgICAgIHBhc3N3b3JkID0gcmVxdWVzdC5QT1NUWydwYXNzd29yZCddCiAgICAgICAgdXNlciA9IGF1dGhlbnRpY2F0ZShyZXF1ZXN0LCB1c2VybmFtZT11c2VybmFtZSwgcGFzc3dvcmQ9cGFzc3dvcmQpCiAgICAgICAgaWYgdXNlcjoKICAgICAgICAgICAgbG9naW4ocmVxdWVzdCwgdXNlcikKICAgICAgICAgICAgcmV0dXJuIHJlZGlyZWN0KCdkYXNoYm9hcmQnKQogICAgcmV0dXJuIHJlbmRlcihyZXF1ZXN0LCAnbG9naW4uaHRtbCcpCgoKQGxvZ2luX3JlcXVpcmVkCmRlZiBkYXNoYm9hcmQocmVxdWVzdCk6CiAgICBtb3ZpZXMgPSBNb3ZpZS5vYmplY3RzLmFsbCgpCiAgICByZXR1cm4gcmVuZGVyKHJlcXVlc3QsICdkYXNoYm9hcmQuaHRtbCcsIHsnbW92aWVzJzogbW92aWVzfSkKCiMgOC4g2YLZiNin2YTYqCBIVE1MOiBsb2dpbi5odG1sLCBkYXNoYm9hcmQuaHRtbCwgbW92aWVfbGlzdC5odG1sICjZitmF2YPZhtmG2Yog2KXYsdiz2KfZhNmH2Kcg2YTZgyDZhNin2K3ZgtmL2Kcg2K3Ys9ioINi32YTYqNmDKQoKIyA5LiDYo9mF2LEg2KfZhNiq2LHYrdmK2YQ6CiMgcHl0aG9uIG1hbmFnZS5weSBtYWtlbWlncmF0aW9ucwojIHB5dGhvbiBtYW5hZ2UucHkgbWlncmF0ZQojIHB5dGhvbiBtYW5hZ2UucHkgY3JlYXRlc3VwZXJ1c2VyCgojIDEwLiDYo9mF2LEg2KfZhNiq2LTYutmK2YQ6CiMgcHl0aG9uIG1hbmFnZS5weSBydW5zZXJ2ZXIK
## مشروع Django لموقع عرض أفلام مع تسجيل دخول ولوحة تحكم وتتبع زوار
# 1. إعداد المشروع (يمكنك تخطي هذا إن كنت أنشأت المشروع بالفعل)
# django-admin startproject moviesite
# cd moviesite
# python manage.py startapp core
# 2. models.py (في تطبيق core)
from django.db import models
from django.contrib.auth.models import User
class Movie(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
poster = models.ImageField(upload_to='posters/')
video_url = models.URLField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Visit(models.Model):
ip = models.GenericIPAddressField()
timestamp = models.DateTimeField(auto_now_add=True)
user_agent = models.TextField()
path = models.CharField(max_length=255)
referrer = models.TextField(blank=True, null=True)
# 3. admin.py
from django.contrib import admin
from .models import Movie, Visit
admin.site.register(Movie)
admin.site.register(Visit)
# 4. middleware.py (داخل core)
from .models import Visit
class VisitTrackingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
ip = request.META.get('REMOTE_ADDR')
user_agent = request.META.get('HTTP_USER_AGENT', '')
referrer = request.META.get('HTTP_REFERER', '')
path = request.path
Visit.objects.create(
ip=ip,
user_agent=user_agent,
path=path,
referrer=referrer
)
return response
# 5. settings.py - أضف التالي:
# في MIDDLEWARE:
# 'core.middleware.VisitTrackingMiddleware',
# في INSTALLED_APPS:
# 'core',
# 6. urls.py (في moviesite/urls.py)
from django.contrib import admin
from django.urls import path, include
from core import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.movie_list, name='movie_list'),
path('login/', views.login_view, name='login'),
path('dashboard/', views.dashboard, name='dashboard'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# 7. views.py (core)
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from .models import Movie
def movie_list(request):
movies = Movie.objects.all()
return render(request, 'movie_list.html', {'movies': movies})
def login_view(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user:
login(request, user)
return redirect('dashboard')
return render(request, 'login.html')
@login_required
def dashboard(request):
movies = Movie.objects.all()
return render(request, 'dashboard.html', {'movies': movies})
# 8. قوالب HTML: login.html, dashboard.html, movie_list.html (يمكنني إرسالها لك لاحقًا حسب طلبك)
# 9. أمر الترحيل:
# python manage.py makemigrations
# python manage.py migrate
# python manage.py createsuperuser
# 10. أمر التشغيل:
# python manage.py runserver