first commit
This commit is contained in:
0
blog/__init__.py
Normal file
0
blog/__init__.py
Normal file
95
blog/admin.py
Normal file
95
blog/admin.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from blog.models import Category, Tags, Post, Comment, CategoryView
|
||||
|
||||
|
||||
# Register your models here.
|
||||
class PostAdmin(admin.ModelAdmin):
|
||||
list_display = ('title', 'post_resim', 'is_active', 'post_kategorileri', 'slug')
|
||||
list_filter = ('is_active', 'categories')
|
||||
search_fields = ('title', 'is_active', 'slug', 'content')
|
||||
list_editable = ('is_active', 'slug',) # Removed 'price' as it is not a field
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
|
||||
def formatted_hit_count(self, obj):
|
||||
return obj.current_hit_count if obj.current_hit_count > 0 else '-'
|
||||
|
||||
formatted_hit_count.admin_order_field = 'hit_count'
|
||||
formatted_hit_count.short_description = 'Hits'
|
||||
|
||||
def post_tags(self, obj):
|
||||
tags = '<ul>'
|
||||
for tag in obj.tags.all():
|
||||
tags += '<li>' + tag.tag + '</li>'
|
||||
tags += '</ul>'
|
||||
return mark_safe(tags)
|
||||
|
||||
def post_kategorileri(self, obj):
|
||||
html = '<ul>'
|
||||
for category in obj.categories.all():
|
||||
html += '<li>' + category.title + '</li>'
|
||||
html += '</ul>'
|
||||
return mark_safe(html)
|
||||
|
||||
def post_resim(self, obj):
|
||||
if obj.image:
|
||||
return mark_safe(
|
||||
'<a href="/admin/post/post/{}/change/#id_images" onclick="window.location.href=\'/admin/post/post/{}/change/#id_images\'; return false;"><img src="{}" width="50" height="50" style="object-fit: cover; cursor: pointer;" title="Resmi değiştirmek için tıklayın" /></a>'.format(
|
||||
obj.id, obj.id, obj.image.url))
|
||||
return mark_safe(
|
||||
'<a href="/admin/post/post/{}/change/#id_images" onclick="window.location.href=\'/admin/post/post/{}/change/#id_images\'; return false;">Resim Yok</a>'.format(
|
||||
obj.id, obj.id))
|
||||
|
||||
post_resim.short_description = 'Kurs Resmi'
|
||||
|
||||
|
||||
admin.site.register(Post, PostAdmin)
|
||||
|
||||
|
||||
class CategoryAdmin(admin.ModelAdmin):
|
||||
list_display = ('title', 'parent_category', 'is_active', 'created_at', 'order') # Removed 'view_count' and 'unique_view_count'
|
||||
list_filter = ('title', 'is_active', 'created_at', 'parent')
|
||||
search_fields = ('title', 'is_active', 'slug')
|
||||
list_editable = ('is_active', 'order')
|
||||
|
||||
class Meta:
|
||||
model = Category
|
||||
|
||||
def parent_category(self, obj):
|
||||
if obj.parent:
|
||||
return obj.parent.title
|
||||
return "Ana Kategori"
|
||||
|
||||
parent_category.short_description = 'Üst Kategori'
|
||||
|
||||
|
||||
admin.site.register(Category, CategoryAdmin)
|
||||
|
||||
|
||||
class TagsAdmin(admin.ModelAdmin):
|
||||
list_display = ('tag', 'created_at',)
|
||||
list_filter = ('tag',)
|
||||
search_fields = ('tag',)
|
||||
|
||||
class Meta:
|
||||
model = Tags
|
||||
|
||||
|
||||
admin.site.register(Tags, TagsAdmin)
|
||||
|
||||
|
||||
class CategoryViewAdmin(admin.ModelAdmin):
|
||||
list_display = ('category', 'ip_address', 'created_at')
|
||||
list_filter = ('created_at', 'category')
|
||||
search_fields = ('ip_address', 'category__title')
|
||||
readonly_fields = ('category', 'ip_address', 'user_agent', 'created_at')
|
||||
|
||||
class Meta:
|
||||
model = CategoryView
|
||||
|
||||
|
||||
admin.site.register(CategoryView, CategoryViewAdmin)
|
||||
admin.site.register(Comment)
|
||||
5
blog/apps.py
Normal file
5
blog/apps.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class BlogConfig(AppConfig):
|
||||
name = 'blog'
|
||||
123
blog/migrations/0001_initial.py
Normal file
123
blog/migrations/0001_initial.py
Normal file
@@ -0,0 +1,123 @@
|
||||
# Generated by Django 6.0 on 2025-12-19 12:36
|
||||
|
||||
import autoslug.fields
|
||||
import core.utils
|
||||
import django.db.models.deletion
|
||||
import imagekit.models.fields
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Tags',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('tag', models.CharField(max_length=254, verbose_name='Post Tagları')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Oluşturulma Tarihi')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Güncelleme Tarihi')),
|
||||
('is_active', models.BooleanField(choices=[(True, 'Evet'), (False, 'Hayır')], default=True, verbose_name='Yayındamı')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Post Tagı',
|
||||
'verbose_name_plural': 'Post Tagları',
|
||||
'db_table': 'tags',
|
||||
'ordering': ['-created_at'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Category',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=254, verbose_name='Kategori')),
|
||||
('keywords', models.CharField(max_length=254, verbose_name='Seo Kelimeleri Aralarına Virgül Koyunuz')),
|
||||
('description', models.CharField(max_length=254, verbose_name='Açıklama')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Oluşturulma Tarihi')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Güncelleme Tarihi')),
|
||||
('is_active', models.BooleanField(choices=[(True, 'Evet'), (False, 'Hayır')], default=True, verbose_name='Yayındamı')),
|
||||
('order', models.IntegerField(db_index=True, default=1, verbose_name='Görüntülenme Sırası')),
|
||||
('slug', autoslug.fields.AutoSlugField(blank=True, editable=True, max_length=250, populate_from='title', unique=True)),
|
||||
('image', imagekit.models.fields.ProcessedImageField(blank=True, null=True, upload_to=core.utils.UniquePathAndRename('uploads/category'), verbose_name='Resim 630 x 653 Olmali ve Transparan PNG Olmali')),
|
||||
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child', to='blog.category', verbose_name='Üst Kategorisi')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Post Kategori',
|
||||
'verbose_name_plural': 'Post Kategorilerileri',
|
||||
'db_table': 'categories',
|
||||
'ordering': ['order'],
|
||||
'unique_together': {('slug', 'parent')},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Post',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=254, verbose_name='Post Başlığı')),
|
||||
('content', models.TextField(blank=True, null=True, verbose_name='Post İçeriği')),
|
||||
('keywords', models.CharField(max_length=254, verbose_name='Seo Kelimeleri Aralarına Virgül Koyunuz')),
|
||||
('image', imagekit.models.fields.ProcessedImageField(blank=True, null=True, upload_to=core.utils.UniquePathAndRename('uploads/post'))),
|
||||
('video', models.CharField(blank=True, default='none', max_length=254, null=True, verbose_name='Video')),
|
||||
('slug', autoslug.fields.AutoSlugField(blank=True, editable=True, max_length=250, populate_from='title', unique=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Oluşturulma Tarihi')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Güncelleme Tarihi')),
|
||||
('is_active', models.BooleanField(choices=[(True, 'Evet'), (False, 'Hayır')], default=True, verbose_name='Yayındamı ?')),
|
||||
('is_front', models.BooleanField(choices=[(True, 'Evet'), (False, 'Hayır')], default=True, verbose_name='Önde Görünsünmü ?')),
|
||||
('categories', models.ManyToManyField(related_name='c_categories', to='blog.category', verbose_name='Post Kategorisi')),
|
||||
('parent', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child', to='blog.post', verbose_name='Konular')),
|
||||
('tags', models.ManyToManyField(related_name='tags', to='blog.tags', verbose_name='Post Tagları')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Post',
|
||||
'verbose_name_plural': 'Posts',
|
||||
'db_table': 'posts',
|
||||
'ordering': ['created_at'],
|
||||
'unique_together': {('slug',)},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CategoryView',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('ip_address', models.GenericIPAddressField(verbose_name='IP Adresi')),
|
||||
('user_agent', models.TextField(blank=True, null=True, verbose_name='User Agent')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Ziyaret Tarihi')),
|
||||
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='category_views', to='blog.category')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Kategori Ziyareti',
|
||||
'verbose_name_plural': 'Kategori Ziyaretleri',
|
||||
'db_table': 'category_views',
|
||||
'indexes': [models.Index(fields=['category', 'ip_address', 'created_at'], name='category_vi_categor_234334_idx')],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Comment',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(max_length=254, verbose_name='Yorum Başlığı')),
|
||||
('body', models.TextField(verbose_name='Yorum')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Oluşturulma Tarihi')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Güncelleme Tarihi')),
|
||||
('is_active', models.BooleanField(choices=[(True, 'Evet'), (False, 'Hayır')], default=True, verbose_name='Yayındamı')),
|
||||
('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='title', unique=True)),
|
||||
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child', to='blog.comment')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cuser', to=settings.AUTH_USER_MODEL)),
|
||||
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='_product', to='blog.post')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Post Yorum',
|
||||
'verbose_name_plural': 'Post Yorumları',
|
||||
'db_table': 'comments',
|
||||
'ordering': ['-created_at'],
|
||||
'unique_together': {('slug', 'parent')},
|
||||
},
|
||||
),
|
||||
]
|
||||
0
blog/migrations/__init__.py
Normal file
0
blog/migrations/__init__.py
Normal file
187
blog/models.py
Normal file
187
blog/models.py
Normal file
@@ -0,0 +1,187 @@
|
||||
from autoslug import AutoSlugField
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from imagekit.models import ProcessedImageField
|
||||
from pilkit.processors import ResizeToFill
|
||||
|
||||
from core.utils import image_optimizer
|
||||
|
||||
|
||||
# Create your models here.
|
||||
class PCategory(models.Model):
|
||||
aktif = (
|
||||
(True, 'Evet'),
|
||||
(False, 'Hayır'),
|
||||
)
|
||||
title = models.CharField(max_length=254, verbose_name="Kategori")
|
||||
keywords = models.CharField(max_length=254, verbose_name="Seo Kelimeleri Aralarına Virgül Koyunuz")
|
||||
description = models.CharField(max_length=254, verbose_name="Açıklama")
|
||||
created_at = models.DateTimeField(auto_now_add=True, editable=False, verbose_name="Oluşturulma Tarihi")
|
||||
updated_at = models.DateTimeField(auto_now=True, editable=False, verbose_name="Güncelleme Tarihi")
|
||||
is_active = models.BooleanField(default=True, verbose_name='Yayındamı', choices=aktif)
|
||||
order = models.IntegerField(verbose_name='Görüntülenme Sırası', default=1, db_index=True)
|
||||
slug = AutoSlugField(populate_from='title', null=False, unique=True, editable=True, db_index=True, max_length=250,
|
||||
blank=True)
|
||||
parent = models.ForeignKey('self', related_name='child', on_delete=models.CASCADE, blank=True, null=True,
|
||||
verbose_name='Üst Kategorisi')
|
||||
image = ProcessedImageField(**image_optimizer('uploads/category', 300, 300, 85, 'PNG'),
|
||||
verbose_name='Resim 630 x 653 Olmali ve Transparan PNG Olmali', blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["order"]
|
||||
db_table = 'p_categories'
|
||||
verbose_name_plural = "Post Kategorilerileri"
|
||||
verbose_name = "Post Kategori"
|
||||
unique_together = ('slug', 'parent',)
|
||||
|
||||
def get_slug(self):
|
||||
slug = self.title.replace('ı', "i").replace('İ', 'i')
|
||||
number = 1
|
||||
while Category.objects.filter(slug=slug).exists():
|
||||
slug = '{}-{}'.format(slug, number)
|
||||
number += 1
|
||||
return slug
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.slug:
|
||||
self.slug = self.get_slug()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
full_path = [self.title]
|
||||
k = self.parent
|
||||
while k is not None:
|
||||
full_path.append(k.title)
|
||||
k = k.parent
|
||||
return ' -> '.join(full_path[::-1])
|
||||
|
||||
|
||||
class PTags(models.Model):
|
||||
aktif = (
|
||||
(True, 'Evet'),
|
||||
(False, 'Hayır'),
|
||||
)
|
||||
tag = models.CharField(max_length=254, verbose_name="Post Tagları")
|
||||
created_at = models.DateTimeField(auto_now_add=True, editable=False, verbose_name="Oluşturulma Tarihi")
|
||||
updated_at = models.DateTimeField(auto_now=True, editable=False, verbose_name="Güncelleme Tarihi")
|
||||
is_active = models.BooleanField(default=True, verbose_name='Yayındamı', choices=aktif)
|
||||
|
||||
class Meta:
|
||||
ordering = ["-created_at"]
|
||||
db_table = 'p_tags'
|
||||
verbose_name_plural = "Post Tagları"
|
||||
verbose_name = "Post Tagı"
|
||||
|
||||
def __str__(self):
|
||||
return self.tag
|
||||
|
||||
|
||||
class PPost(models.Model):
|
||||
aktif = (
|
||||
(True, 'Evet'),
|
||||
(False, 'Hayır'),
|
||||
)
|
||||
|
||||
title = models.CharField(max_length=254, verbose_name="Post Başlığı")
|
||||
content = models.TextField(blank=True, null=True, verbose_name='Post İçeriği')
|
||||
categories = models.ManyToManyField(Category, verbose_name="Post Kategorisi", related_name='c_categories')
|
||||
keywords = models.CharField(max_length=254, verbose_name="Seo Kelimeleri Aralarına Virgül Koyunuz")
|
||||
tags = models.ManyToManyField(Tags, verbose_name="Post Tagları", related_name='tags')
|
||||
image = ProcessedImageField(**image_optimizer('uploads/post', 700, 450, 90, 'avif'), null=True, blank=True)
|
||||
video = models.CharField(verbose_name="Video", null=True, blank=True, max_length=254, default='none')
|
||||
slug = AutoSlugField(populate_from='title', null=False, unique=True, editable=True, db_index=True, max_length=250,
|
||||
blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True, editable=False, verbose_name="Oluşturulma Tarihi")
|
||||
updated_at = models.DateTimeField(auto_now=True, editable=False, verbose_name="Güncelleme Tarihi")
|
||||
is_active = models.BooleanField(default=True, verbose_name='Yayındamı ?', choices=aktif)
|
||||
is_front = models.BooleanField(default=True, verbose_name='Önde Görünsünmü ?', choices=aktif)
|
||||
parent = models.ForeignKey('self', related_name='child', on_delete=models.CASCADE, blank=True, null=True,
|
||||
editable=False,
|
||||
verbose_name='Konular')
|
||||
|
||||
class Meta:
|
||||
ordering = ["created_at"]
|
||||
db_table = 'p_posts'
|
||||
verbose_name_plural = "Posts"
|
||||
verbose_name = "Post"
|
||||
unique_together = ('slug',)
|
||||
|
||||
def get_slug(self):
|
||||
slug = self.title.replace('ı', "i").replace('İ', 'i')
|
||||
number = 1
|
||||
while Post.objects.filter(slug=slug).exists():
|
||||
slug = '{}-{}'.format(slug, number)
|
||||
number += 1
|
||||
return slug
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.slug:
|
||||
self.slug = self.get_slug()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return f"Postlar: {self.title}"
|
||||
|
||||
|
||||
class PCategoryView(models.Model):
|
||||
"""Kategori ziyaretlerini takip etmek için model"""
|
||||
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='category_views')
|
||||
ip_address = models.GenericIPAddressField(verbose_name='IP Adresi')
|
||||
user_agent = models.TextField(blank=True, null=True, verbose_name='User Agent')
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name='Ziyaret Tarihi')
|
||||
|
||||
class Meta:
|
||||
db_table = 'p_category_views'
|
||||
verbose_name = 'Kategori Ziyareti'
|
||||
verbose_name_plural = 'Kategori Ziyaretleri'
|
||||
# unique_together kısıtlamasını kaldırdık - artık günlük bazda kontrol edeceğiz
|
||||
indexes = [
|
||||
models.Index(fields=['category', 'ip_address', 'created_at']),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.category.title} - {self.ip_address} - {self.created_at.strftime('%Y-%m-%d %H:%M')}"
|
||||
|
||||
|
||||
class PComment(models.Model):
|
||||
aktif = (
|
||||
(True, 'Evet'),
|
||||
(False, 'Hayır'),
|
||||
)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='cuser')
|
||||
product = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='_product')
|
||||
title = models.CharField(max_length=254, verbose_name="Yorum Başlığı")
|
||||
body = models.TextField(verbose_name='Yorum')
|
||||
created_at = models.DateTimeField(auto_now_add=True, editable=False, verbose_name="Oluşturulma Tarihi")
|
||||
updated_at = models.DateTimeField(auto_now=True, editable=False, verbose_name="Güncelleme Tarihi")
|
||||
is_active = models.BooleanField(default=True, verbose_name='Yayındamı', choices=aktif)
|
||||
slug = AutoSlugField(populate_from='title', null=False, unique=True, editable=False, db_index=True)
|
||||
parent = models.ForeignKey('self', related_name='child', on_delete=models.CASCADE, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["-created_at"]
|
||||
db_table = 'p_comments'
|
||||
verbose_name_plural = "Post Yorumları"
|
||||
verbose_name = "Post Yorum"
|
||||
unique_together = ('slug', 'parent',)
|
||||
|
||||
def get_slug(self):
|
||||
slug = self.title.replace('ı', "i").replace('İ', 'i')
|
||||
number = 1
|
||||
while Comment.objects.filter(slug=slug).exists():
|
||||
slug = '{}-{}'.format(slug, number)
|
||||
number += 1
|
||||
return slug
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.slug:
|
||||
self.slug = self.get_slug()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
full_path = [self.title]
|
||||
k = self.parent
|
||||
while k is not None:
|
||||
full_path.append(k.title)
|
||||
k = k.parent
|
||||
return ' -> '.join(full_path[::-1])
|
||||
3
blog/tests.py
Normal file
3
blog/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
0
blog/urls.py
Normal file
0
blog/urls.py
Normal file
3
blog/views.py
Normal file
3
blog/views.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
Reference in New Issue
Block a user