Django admin.py টিউটোরিয়াল পার্টসমূহ
- পার্ট ১: Django Admin এর ভূমিকা এবং মৌলিক ধারণা
- Django Admin কী এবং এর গুরুত্ব।
- Django Admin এর মৌলিক কাঠামো ও কার্যপ্রণালী।
- পার্ট ২: Admin Panel কনফিগারেশন
- Django Admin এ লগইন এবং সেটআপ করা।
admin.pyফাইল তৈরি ও সেটআপ করা।
- পার্ট ৩: Model Registration in Admin
- Django এর মডেলগুলি Admin Panel এ কিভাবে নিবন্ধন করবেন।
admin.site.register()ফাংশনের ব্যবহার।
- পার্ট ৪: Model Admin Customization
- Model Admin কাস্টমাইজেশন:
ModelAdminক্লাস এবং এর অপশন। - Fields, list_display, list_filter, search_fields, ordering ইত্যাদি।
- Model Admin কাস্টমাইজেশন:
- পার্ট ৫: Inline Model Admin ব্যবহার
- Inline Model Admin কিভাবে কাজ করে এবং কেন প্রয়োজন।
- Related মডেলগুলি Admin Panel এ কিভাবে ইনলাইন হিসেবে দেখানো যায়।
- পার্ট ৬: Admin Actions কাস্টমাইজেশন
- কাস্টম অ্যাকশন তৈরি এবং Admin Panel এ যুক্ত করা।
- কিভাবে একাধিক নির্বাচিত অবজেক্টের উপর অ্যাকশন প্রয়োগ করবেন।
- পার্ট ৭: Admin Interface Styling এবং UI কাস্টমাইজেশন
- Admin ইন্টারফেসের জন্য CSS এবং JavaScript যোগ করা।
- Django Admin UI কাস্টমাইজেশনের পদ্ধতি।
- পার্ট ৮: Filtering এবং Searching Options
- Advanced Filtering এবং Searching যোগ করা।
- কাস্টম ফিল্টারস তৈরি ও যুক্ত করা।
- পার্ট ৯: Permissions and Access Control
- Admin Panel এ Permissions কিভাবে পরিচালনা করবেন।
- User Permissions এবং Group Permissions এর ব্যবহার।
- পার্ট ১০: Django Admin তে Validation এবং Error Handling
- Model Level Validation এবং Custom Validation Logic।
- Admin Panel এ Validation Error Management।
- পার্ট ১১: Admin Dashboard কাস্টমাইজেশন
- Admin Dashboard এ কাস্টম স্ট্যাটিস্টিক্স এবং চার্ট যোগ করা।
- Dashboard এর লেআউট পরিবর্তন এবং কাস্টমাইজ করা।
- পার্ট ১২: Advanced Admin Features
- Django Admin এ Ajax Integration এবং Dynamic Fields।
- Bulk Edit এবং Batch Processing এর মাধ্যমে কার্যকরী কর্মপ্রণালী।
- পার্ট ১৩: Third-party Admin Packages
- Django Admin এর জন্য তৃতীয় পক্ষের প্যাকেজ এবং কিভাবে এগুলি ব্যবহার করবেন।
- Popular Admin Extensions ও তাদের সুবিধাসমূহ।
- পার্ট ১৪: Testing Django Admin Customizations
- Django Admin Customizations এর Unit Testing এবং Integration Testing।
- কিভাবে Admin Panel এর কার্যকারিতা টেস্ট করবেন।
- পার্ট ১৫: Deployment and Best Practices for Django Admin
- Django Admin Deployment এর জন্য সেরা কৌশল।
- নিরাপত্তা, কার্যকারিতা এবং ব্যবস্থাপনা সংক্রান্ত কিছু সেরা অভ্যাস।
মডেলকে অ্যাডমিন প্যানেলে যোগ করি
মডেলকে অ্যাডমিন প্যানেল এ যুক্ত করা
Comment
মডেলকে Django এডমিন প্যানেলে যোগ করা খুবই সহজ । নিম্নলিখিত মাধ্যমে আপনি মডেলটি আপনার Django প্রোজেক্টে এডমিন প্যানেলে সংযুক্ত করতে পারেন:Comment
প্রথমত, মডেল ডেফিনিশন:Comment
আমরা মডেল ডেফিনিশন থেকে শুরু করব। মডেল ডেফিনিশন দিচ্ছি:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
মডেল অ্যাডমিন:Comment
এখন আমরা মডেলটি এডমিন প্যানেলে যোগ করার জন্য এডমিন ক্লাস তৈরি করব।
from django.contrib import admin
from .models import Post
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'pub_date')
search_fields = ('title', 'author__name') # Assuming Author model has a 'name' field
list_filter = ('author',)
ordering = ('-pub_date',)
readonly_fields = ('pub_date',)
list_display (তালিকা_প্রদর্শন): এটি ডিজাঙ্গো এডমিন তালিকা দৃশ্যতা নির্ধারণ করে, এই ফিল্ডগুলি তালিকা ভিউতে প্রদর্শিত হবে।Comment
search_fields (সার্চ_ক্ষেত্র): এটি ডিজাঙ্গো এডমিন তালিকা ভিউতে সার্চ বক্স যুক্ত করে, যার মাধ্যমে আপনি ডেটা সার্চ করতে পারবেন।Comment
list_filter (তালিকা_ফিল্টার): এটি ডিজাঙ্গো এডমিন তালিকা ভিউতে ফিল্টার অপশন যুক্ত করে, যার মাধ্যমে আপনি ডেটা ফিল্টার করতে পারবেন।Comment
ordering (সাজানো): এটি ডিজাঙ্গো এডমিন তালিকা ভিউে ডেটা সাজানোর ডিফল্ট আদান-প্রদান নির্ধারণ করে।Comment
readonly_fields দেয়ার কারণে অ্যাডমিন প্যানেল এ সেভ করার সময় কোন ইনপুট ফিল্ড শো করবে না।Comment
prepopulated_fields
Comment
prepopulated_fields বলতে বুঝি কোন একটা ফিল্ড ইনপুট দিলে অন্য একটি ফিল্ড ওই ইনপুট ধারণ করা আরো সহজ ভাবে বললে মনে করি আমাদের একটি ব্লগ app আছে যার একটি title ও slug নামে ফিল্ড আছে আমরা চাচ্ছি title এ যা লিখবো তা slug এ prepopulated হয়ে বসে যাবে এটা করার জন্য admin.py তে modelAdmin ক্লাস এ নিচের মত লিখতে হয় মনে করি আমাদের মডেল এর নাম POST
#models.py
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)#admin.py
from .models import Post
class PostAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('title',)}
admin.site.register(Post,PostAdmin)Custom Admin Panel
এর আগে কাজ করার জন্য আমি আমার অ্যাডমিন প্যানেলটি বিভিন্ন ভাবে কাস্টোমাইজের মাদ্ধমে একটা লুক দিয়েছিলাম ঐটা কিভাবে যেকোন প্রজেক্ট এ ব্যবহার করবো সেই টিউটোরিয়াল আজকে দেব।
#settings.py
TEMPLATES = [
{
'DIRS': [BASE_DIR / 'templates'], # ঠিক এইরকম
}
]
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
STATIC_ROOT=(BASE_DIR/ "assets/")
import os
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'assets/media/')প্রজেক্টস ফোল্ডারে static ফোল্ডার নাম এ ফোল্ডার তৈরী করি অথবা স্ট্যাটিক ফোল্ডারে নিচের লিংকের ফাইল পেস্ট করি
staticfile অথবা এই লিংকে আপলোড করা আছে
টেম্প্লেটস ফোল্ডারে নিচের টেম্প্লেটস ফাইলটি পেস্ট করি link
এখন আমাদের অ্যাডমিন প্যানেল পরিবর্তন হয়ে যাবে কিন্তু পরবর্তীতে কোনো মডেল অ্যাডমিন প্যানেল এ যোগ করলে সেটা django এর ডিফল্ট অ্যাডমিন প্যানেল টেমপ্লেট ব্যবহার করবে আমাদের তা ব্যবহার করার জন্য যখন admin.py ফাইলে মডেলকে রেজিস্টার করবো তখন টেম্পলেট বলে দেব।
@admin.register(Teacher)
class TeacherAdmin(admin.ModelAdmin):
change_form_template = 'change_form.html'
class Media:
css = {
'all': ('css/bootstrap.min.css','css/admin_styles.css'),
} Site Heading And Title Change
অ্যাডমিন প্যানেল এর টাইটেল হেডিং ইত্যাদি পরিবর্তনের জন্য আমরা প্রজেক্ট এর urls.py ব্যবহার করতে পারি। Comment

project urls.py
#project urls.py
from django.contrib import admin
from django.templatetags.static import static
admin.site.site_header = "Ayat Solution"
admin.site.site_title = "Ayat Industry Automation System"
admin.site.index_title = "Welcome to the Admin Site"
Add Custom Css And Js
প্রথমে প্রজেক্টের রুট ফোল্ডার যেখানে manage.py ফাইল আছে সেখানে templates ফোল্ডারের মধ্যে admin নামে একটি ফোল্ডার তৈরী করি এবং তার মধ্যে base_site.html নামে একটি ফাইল তৈরী করি।Comment
templates/admin/base_site.html
extrastyle ব্লকের মধ্যে আমরা css এবং js ফাইল লোকেশন বলে দেব।
{% extends "admin/base.html" %}
{% load static %}
{% block title %}Ayat{% endblock %}
{% block extrastyle %}
{{ block.super }}
<script src="{% static 'js/custom.js' %}"></script>
<style>
#header {
background-image: url('{% static "images/ayat.png" %}');
background-repeat: no-repeat;
background-position: left center;
background-size: contain;
}
div.flex-container:has(#id_TotalAmount,#id_TotalQty) {
/* CSS styles for the selected element */
/* For example: */
display:none
}
</style>
{% endblock %}এডমিন প্যানেলে পিডিএফ এক্সপোর্ট বাটন যোগ করি
Install Required Packages:
pip install reportlab django-admin-actions
Create the Model:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
Run Migrations:
python manage.py makemigrations
python manage.py migrate
admin.py
from django.contrib import admin
from django.http import HttpResponse
from reportlab.pdfgen import canvas
from io import BytesIO
from django_admin_actions.admin import ActionsModelAdmin
from .models import Post
def generate_pdf(modeladmin, request, queryset):
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="posts.pdf"'
buffer = BytesIO()
p = canvas.Canvas(buffer)
for post in queryset:
p.drawString(100, 700, f"Title: {post.title}")
p.drawString(100, 680, f"Content: {post.content}")
p.showPage()
p.save()
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return response
generate_pdf.short_description = "Generate PDF"
@admin.register(Post)
class PostAdmin(ActionsModelAdmin):
list_display = ['title', 'content', 'created_at']
actions = [generate_pdf]
কাস্টম ফর্ম যোগ করুন মডেল ফর্ম কাস্টোমাইজ করি
form.py তে ফর্ম বানাই
from django import forms
from .models import BusinessPartner
class CustomBusinessPartnerForm(forms.ModelForm):
class Meta:
model = BusinessPartner
fields = '__all__' # সব ফিল্ড অবশ্যই যোগ করুন
# যেহেতু BusinessPartner মডেলে currency_type এবং vendor_type ফিল্ডের একটি choices ফিল্ড আছে, আমি এটি একটি রেডিও বাটন রুপে দেখাতে চাই
currency_type = forms.ChoiceField(widget=forms.RadioSelect, choices=BusinessPartner.CURRENCY_TYPES)
vendor_type = forms.ChoiceField(widget=forms.RadioSelect, choices=BusinessPartner.VENDOR_TYPES)
এডমিন ফাইলে বলে দেই ফর্ম টেম্পপ্লেট কে
from .models import BusinessPartner
from .forms import CustomBusinessPartnerForm
@admin.register(BusinessPartner)
class BusinessPartnerAdmin(admin.ModelAdmin):
form = CustomBusinessPartnerForm # কাস্টম ফর্ম যোগ করুনমডেলের html টেম্পলেট পরিবর্তন করি
মনেকরি আমরা একটি app এ একটি মডেল বানিয়েছি এবং admin.py ফাইলের মাধ্যমে মডেলকে অ্যাডমিন প্যানেলে যোগ করেছি তাহলে তো ড্যাঙ্গ এর ডিফল্ট ডিজাইন এর টেমপ্লেট শো করবে কিন্তু আমরা তো চাই আমাদের নিজেদের html এর ডিজাইন শো করতে এজন্য আমাদের যা যা করতে হবে।
টেম্পলেট বানানো :
- আমাদের app ফোল্ডারে templates ফোল্ডারের মধ্যে admin নামে ফোল্ডার তৈরী করি
- admin ফোল্ডারের মধ্যে app এর নামে ফোল্ডার বানাই
- app ফোল্ডারে মডেল এর নামে ফোল্ডার বানাই
- মডেল ফোল্ডারে html টেম্পলেট বানাই
Comment
মনেকরি আমাদের app এর নাম salesapp আর মডেল এর নাম item তাহলে ফোল্ডার স্ট্রাকটার হবে নিচের মত

Comment
এবার মডেলকে অ্যাডমিন প্যানেলে যোগ করার সময় টেম্পলেট টি বলে
from django.contrib import admin
from .models import SalesInfo
class SalesInfoAdmin(admin.ModelAdmin):
change_form_template = 'admin/salesapp/item/change_form.html'
admin.site.register(SalesInfo, SalesInfoAdmin)এখন কথা হলো মনের মত যেভাবে খুশি করলে কিছু কিছু এরর শো করবে তার চেয়ে ভালো হয় django এর admin ফোল্ডারে html টেম্পলেট আছে ঐটা আমরা ওভার রাইট করবো এজন্য পাইথনের ইনস্টল ডিরেক্টরি থেকে Python\Python311-32\Lib\site-packages\django\contrib\admin\templates\admin ফোল্ডারে গেলে change_form.html নামে একটি ফাইল আছে ঐটা কপি করে আমাদের টেম্প্লেটস ফোল্ডারে পেস্ট করে এডিট করবো।Comment
breadcrumbs
{% if not is_popup %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
› {% if has_view_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
› {% if add %}{% blocktranslate with name=opts.verbose_name %}Add {{ name }}{% endblocktranslate %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
</div>
{% endblock %}
{% endif %}Add Button
{% block object-tools %}
{% if change and not is_popup %}
<ul class="object-tools">
{% block object-tools-items %}
{% change_form_object_tools %}
{% endblock %}
</ul>
{% endif %}
{% endblock %} {% include "admin/includes/fieldset.html" %}Form
<form class="row" {% if has_file_field %}enctype="multipart/form-data" {% endif %}{% if form_url %}action="{{ form_url }}" {% endif %}method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1">{% endif %}
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
{% if errors %}
<p class="errornote">
{% blocktranslate count counter=errors|length %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktranslate %}
</p>
{{ adminform.form.non_field_errors }}
{% endif %}
</form>উপরের এই কোডের জায়গায় অ্যাডমিন ফোল্ডারের include ফোল্ডার থেকে fieldset.html নামের ফাইল থেকে কোড কপি করে কাস্টমাইজ করবোComment
Block Field Set
{% block field_sets %}
{% for fieldset in adminform %}
{% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %}
{% if fieldset.description %}
<div class="description">{{ fieldset.description|safe }}</div>
{% endif %}
{% for line in fieldset %}
{% if line.fields|length == 1 %}{{ line.errors }}{% else %}<div class="">{% endif %}
{% for field in line %}
{% if not line.fields|length == 1 and not field.is_readonly %}{{ field.errors }}{% endif %}
<div class="col-md-6">
{% if field.is_checkbox %}
{{ field.field }}{{ field.label_tag }}
{% else %}
{{ field.label_tag }}
{% if field.is_readonly %}
<div class="readonly">{{ field.contents }}</div>
{% else %}
{{ field.field }}
{% endif %}
{% endif %}
</div>
{% if field.field.help_text %}
<div class="help"{% if field.field.id_for_label %} id="{{ field.field.id_for_label }}_helptext"{% endif %}>
<div>{{ field.field.help_text|safe }}</div>
</div>
{% endif %}
{% endfor %}
{% if not line.fields|length == 1 %}</div>{% endif %}
{% endfor %}
{% endfor %}
{% endblock %}Submit Button
{% block submit_buttons_bottom %}
<div class="submit-row">
<div class="row">
<div class="col-12">
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="btn btn-primary"{% if show_save_as %} name="_saveasnew"{% endif %}>{% endif %}
{% if show_save_as %}<input type="submit" value="{% trans 'Save as new' %}" class="btn btn-secondary" name="_saveasnew">{% endif %}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" class="btn btn-secondary" name="_addanother">{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" class="btn btn-secondary" name="_continue">{% endif %}
<a href="{% url opts|admin_urlname:'changelist' %}" class="btn btn-secondary ms-2">{% trans "Cancel" %}</a>
</div>
</div>
</div>
{% endblock %}ফিল্ড এর ডিজাইন বুটস্ট্রাপ ফরম্যাটে হবে
মনেকরি আমাদের নিচের মত একটা মডেল আছে।
class Item(models.Model):
code = models.CharField(max_length=25, unique=True,default='')
name = models.CharField(max_length=100, unique=True)
description = models.TextField()
warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE, default=1)
unit = models.ForeignKey(Unit, on_delete=models.SET_DEFAULT, default=1)
price = models.DecimalField(max_digits=10, decimal_places=2, default=0)এখন আমরা এই মডেলকে অ্যাডমিন প্যানেল এ যোগ করবো এবং ফিল্ড এর ডিজাইন বুটস্ট্রাপ ফরম্যাটে হবে এ জন্য যা যা করতে হবে।Comment
আমাদের app ডিরেক্টরিতে widgets.py নামে একটি ফাইল তৈরী করে নিচের কোড লিখতে হবে।Comment
widgets.py
from django.forms import widgets
class CustomFieldWidget(widgets.Widget):
def render(self, name, value, attrs=None, renderer=None):
html = f'''
<div class="custom-field">
<label class="custom-label" for="{name}">{name.capitalize()}</label>
<div class="custom-input">
<input type="text" id="{name}" name="{name}" value="{value}" class="custom-control" />
<!-- Add any additional elements or customization here -->
</div>
</div>
'''
return html
এবার আমাদের admin.py ফাইলে আমাদের মডেলটি অ্যাড করে দিতে হবে এবং ফিল্ড এর স্ট্রাকটার ওভার রাইট করে দিতে হবে নিচের মত।
from django.contrib import admin
from django import forms
from django.db import models
# our widgets
from ItemMasterData.widgets import CustomFieldWidget
# our model
from .models import Item
class ItemAdmin(admin.ModelAdmin):
fields = ('code', 'name', 'description', 'warehouse', 'unit')
formfield_overrides = {
models.CharField: {'widget': CustomFieldWidget},
models.TextField: {'widget': CustomFieldWidget},
# Add overrides for other field types as needed
}
admin.site.register(Item,ItemAdmin)
টেবিল বেসড ফর্মসেট এপ্লিকেশন
মনেকরি আমরা একটি ফরমসেট বেসড crud বানাতে চাচ্ছি যা অ্যাডমিন প্যানেল থেকে এক্সেস করে কাজ সম্পাদন করা যাবে। এজন্য আমরা একটি ফরমসেট বানিয়ে তা অ্যাডমিন প্যানেল এ যোগ করি।CommentComment

Comment
models.py
class DeliveryInfo(models.Model):
delivery_date = models.DateField()
recipient_name = models.CharField(max_length=100)
address = models.CharField(max_length=200)
def __str__(self):
return f"{self.delivery_date} - {self.recipient_name}"
class DeliveryItem(models.Model):
delivery_info = models.ForeignKey(DeliveryInfo, on_delete=models.CASCADE)
item_name = models.CharField(max_length=100)
quantity = models.PositiveIntegerField()
def __str__(self):
return self.item_name
class DeliveryItemInline(admin.TabularInline):
model = DeliveryItem
extra = 1
class DeliveryInfoAdmin(admin.ModelAdmin):
inlines = [DeliveryItemInline]
admin.site.register(DeliveryInfo, DeliveryInfoAdmin)নির্দিষ্ট ইউজারকে মডেলে এক্সেস পারমিশন দেয়া
সুপার অ্যাডমিন হিসাবে অ্যাডমিন প্যানেল এ ঢুকে একজন নির্দিষ্ট ইউজারকে stuff membar বানিয়ে ফরমসেট এর এক্সেস দেই। মনে করি আমাদের ইউজার এর নাম gsm .

Comment
এবার যখন আমাদের gsm ইউজার লগইন করবে নিচের মত দেখতে পাবে।

অ্যাডমিন প্যানেলে জাভাস্ক্রিপ্ট ও css ফাইল যোগ করা
Django এডমিন প্যানেলে JavaScript এবং CSS ফাইল যোগ করার জন্য নিম্নলিখিত পদক্ষেপগুলি অনুসরণ করতে হবে:Comment
প্রথমটি, আপনার static ফোল্ডারে জাভাস্ক্রিপ্ট এবং CSS ফাইলগুলি সংরক্ষণ করুন:Comment
1.স্ট্যাটিক ফাইল সংরক্ষণ: আপনি আপনার প্রোজেক্টের রুট ডিরেক্টরিতে static নামে একটি ফোল্ডার তৈরি করুন, যদি তা নেই, এবং সেখানে জাভাস্ক্রিপ্ট এবং CSS ফাইলগুলি রাখুন।উদাহরণস্বরূপ:
your_project/
├── your_app/
├── static/
│ ├── js/
│ │ ├── your_script.js
│ ├── css/
│ │ ├── your_style.css
├── ...
- জাভাস্ক্রিপ্ট ফাইল সংরক্ষণ: আপনি আপনার জাভাস্ক্রিপ্ট কোড সংরক্ষণ করুন
static/js/ডিরেক্টরির মধ্যে, যেমনyour_script.js।Comment - 2.CSS ফাইল সংরক্ষণ: আপনি আপনার CSS স্টাইল সংরক্ষণ করুন
static/css/ডিরেক্টরির মধ্যে, যেমনyour_style.css।Comment
Comment
admin.py ফাইলে স্ট্যাটিক ফাইল লোড করা: আপনার প্রজেক্টের এডমিন প্যানেলে স্ট্যাটিক ফাইল লোড করতে, আপনার admin.py ফাইলে নিম্নলিখিত কোড যোগ করুন:
from django.contrib import admin
class YourModelAdmin(admin.ModelAdmin):
class Media:
js = ('js/your_script.js',)
defer = True # Add the defer attribute
css = {
'all': ('css/your_style.css',), # আপনার CSS ফাইলের নাম
}
admin.site.register(YourModel, YourModelAdmin) ‘all’ দ্বারা বুঝানো হয়েছে সব ধরণের মিডিয়া তে এই স্টাইল শিট ব্যবহার হবে সাধারণত screen এবং print এর জন্য আলাদা css ব্যবহার হয় সেক্ষেত্রে সেটাও বলে দিতে পারি
class YourModelAdmin(admin.ModelAdmin):
class Media:
css = {
'screen': ('css/screen_style.css',),
'print': ('css/print_style.css',),
}
auto complete fetch data
models.py
from django.db import models
from django.utils import timezone
class SalesOrderInfo(models.Model):
order_number = models.PositiveIntegerField(default=1, unique=True)
customername = models.CharField(max_length=50)
address = models.CharField(max_length=50)
created = models.DateTimeField(default=timezone.now)
def __str__(self):
return f"SalesOrderInfo: {self.order_number}"
class SalesOrderDelivery(models.Model):
order_info = models.ForeignKey(SalesOrderInfo, on_delete=models.CASCADE, null=True, default=None)
item = models.CharField(max_length=50)
quantity = models.PositiveIntegerField(default=0)
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return f"SalesOrderDelivery: {self.item} - {self.quantity}"
class DeliveryOrderInfo(models.Model):
sales_order_number = models.PositiveIntegerField()
customername = models.CharField(max_length=50)
address = models.CharField(max_length=50)
def __str__(self):
return f"DeliveryOrderInfo: {self.sales_order_number}"
class DeliveryOrderItem(models.Model):
delivery_order_info = models.ForeignKey(DeliveryOrderInfo, on_delete=models.CASCADE)
item = models.CharField(max_length=50)
quantity = models.PositiveIntegerField(default=0)
def __str__(self):
return f"DeliveryOrderItem: {self.item} - {self.quantity}"
set static file configuration
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
STATIC_ROOT=(BASE_DIR/ "assets/")
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'assets/media/')admin.py
from django.contrib import admin
from django.forms import inlineformset_factory
from .models import (
SalesOrderInfo,
SalesOrderDelivery,
DeliveryOrderInfo,
DeliveryOrderItem,
)
class SalesOrderDeliveryInline(admin.TabularInline):
model = SalesOrderDelivery
class SalesOrderInfoAdmin(admin.ModelAdmin):
inlines = [SalesOrderDeliveryInline]
class DeliveryOrderItemInline(admin.TabularInline):
model = DeliveryOrderItem
class DeliveryOrderInfoAdmin(admin.ModelAdmin):
inlines = [DeliveryOrderItemInline]
class Media:
js = ('js/fetch_sales_order_info.js',)
defer = True # Add the defer attribute
admin.site.register(SalesOrderInfo, SalesOrderInfoAdmin)
admin.site.register(DeliveryOrderInfo, DeliveryOrderInfoAdmin)
views.py
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index (request):
return HttpResponse('h')
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from .models import SalesOrderInfo, SalesOrderDelivery
@csrf_exempt
def get_sales_order_info(request):
if request.method == 'POST':
sales_order_number = request.POST.get('sales_order_number')
try:
sales_order_info = SalesOrderInfo.objects.get(order_number=sales_order_number)
data = {
'customername': sales_order_info.customername,
'address': sales_order_info.address,
}
return JsonResponse(data)
except SalesOrderInfo.DoesNotExist:
return JsonResponse({})
@csrf_exempt
def get_sales_order_info(request):
if request.method == 'POST':
sales_order_number = request.POST.get('sales_order_number')
try:
sales_order_info = SalesOrderInfo.objects.get(order_number=sales_order_number)
data = {
'customername': sales_order_info.customername,
'address': sales_order_info.address,
}
return JsonResponse(data)
except SalesOrderInfo.DoesNotExist:
return JsonResponse({})
@csrf_exempt
def fetch_sales_order_delivery(request):
order_number = request.GET.get('order_number')
sales_order_info = SalesOrderInfo.objects.filter(order_number=order_number).first()
if not sales_order_info:
raise Http404("Sales order not found")
sales_order_delivery_items = SalesOrderDelivery.objects.filter(order_info=sales_order_info)
unique_items = sales_order_delivery_items.values('item').distinct()
items = [{'item': item['item'], 'quantity': sales_order_delivery_items.filter(item=item['item']).values('quantity').first()['quantity']} for item in unique_items]
return JsonResponse(items, safe=False)urls.py
from django.urls import path
from . import views
urlpatterns = [
path('',views.index,name='index'),
path('get_sales_order_info/', views.get_sales_order_info, name='get_sales_order_info'),
path('fetch_sales_order_delivery/', views.fetch_sales_order_delivery, name='fetch_sales_order_delivery'),
]static/js/fetch_sales_order_info.js
(function($) {
$(document).ready(function() {
$('#id_sales_order_number').on('change', function() {
var orderno = $(this).val();
if (orderno) {
$.ajax({
type: 'POST',
url: '/myapp/get_sales_order_info/',
data: {
'sales_order_number': orderno,
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
success: function(data) {
if (data.customername) {
$('#id_customername').val(data.customername);
$('#id_address').val(data.address);
} else {
$('#id_customername').val('');
$('#id_address').val('');
}
},
error: function() {
// Handle error case
}
});
} else {
$('#id_customername').val('');
$('#id_address').val('');
}
});
});
})(jQuery);
(function($) {
$(document).ready(function() {
$('#id_sales_order_number').on('change', function() {
var orderno = $(this).val();
if (orderno) {
fetchSalesOrderDelivery(orderno); // Call the function to fetch delivery items
}
});
// Function to fetch sales order delivery items
function fetchSalesOrderDelivery(orderno) {
$.ajax({
type: 'GET',
url: '/myapp/fetch_sales_order_delivery/',
data: {
'order_number': orderno
},
success: function(data) {
populateSelectBoxes(data);
},
error: function() {
// Handle error case
}
});
}
// Function to populate select boxes with fetched data
function populateSelectBoxes(data) {
$('.dynamic-deliveryorderitem_set select[id^="id_deliveryorderitem_set-"][id$="-item"]').each(function() {
var selectBox = $(this);
selectBox.empty(); // Clear existing options
$.each(data, function(index, item) {
selectBox.append($('<option></option>').attr('value', item.item).text(item.item));
});
});
}
});
})(jQuery);
bill of materials
https://chat.openai.com/share/99cb92bf-404a-42f2-8346-fc87a89a4bbaComment
settings.py
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
STATIC_ROOT=(BASE_DIR/ "assets/")
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'assets/media/')models.py
class BillOfMaterials(models.Model):
code = models.CharField(max_length=20)
name = models.CharField(max_length=100)
bomtype = models.CharField(max_length=20)
quantity = models.DecimalField(max_digits=10, decimal_places=4)
class ChildComponent(models.Model):
bill_of_materials = models.ForeignKey(BillOfMaterials, on_delete=models.CASCADE, related_name='child_components')
code = models.CharField(max_length=20)
name = models.CharField(max_length=100)
uom = models.CharField(max_length=20)
quantity = models.DecimalField(max_digits=10, decimal_places=4)
class Production(models.Model):
name = models.CharField(max_length=100)
quantity = models.DecimalField(max_digits=10, decimal_places=4)
def __str__(self):
return self.name
class ProductionComponent(models.Model):
production = models.ForeignKey(Production, on_delete=models.CASCADE, related_name='production_components')
code = models.CharField(max_length=20)
name = models.CharField(max_length=100)
uom = models.CharField(max_length=20)
quantity = models.DecimalField(max_digits=10, decimal_places=4)
def __str__(self):
return self.name
admin.py
from django.contrib import admin
from django.forms import inlineformset_factory
from .models import (
BillOfMaterials,
ChildComponent,
Production,
ProductionComponent
)
# Bill Of Materials
class ChildComponentInline(admin.TabularInline):
model = ChildComponent
class BillOfMaterialsAdmin(admin.ModelAdmin):
inlines = [ChildComponentInline]
admin.site.register(BillOfMaterials, BillOfMaterialsAdmin)
# Production Order
class ProductionComponentInline(admin.TabularInline):
model = ProductionComponent
class ProductionAdmin(admin.ModelAdmin):
inlines = [ProductionComponentInline]
class Media:
js = ('js/fetch_sales_order_info.js',)
defer = True # Add the defer attribute
admin.site.register(Production, ProductionAdmin)create static/js folder and store fetch_sales_order_info.js
(function ($) {
$(document).ready(function(){
$('#id_name, #id_quantity').on('change',function(){
var initialname = $('#id_name').val();
var initialquantity = $('#id_quantity').val();
if (initialname.trim() !== '' && initialquantity.trim() !== '') {
$.ajax({
type: 'POST',
url: '/library/ajax/',
data: {
'name': initialname,
'quantity': initialquantity
},
dataType: 'json',
success: function(response){
updateFormset(response);
// $('#id_production_components-0-quantity').val(response.quantity);
}
});
}
});
function updateFormset(data) {
var formsetTable = $('table');
formsetTable.empty();
// Add table header
var tableHeader = $('<thead>').appendTo(formsetTable);
var headerRow = $('<tr>').appendTo(tableHeader);
$('<th>').addClass('column-code required').text('Code').appendTo(headerRow);
$('<th>').addClass('column-name required').text('Name').appendTo(headerRow);
$('<th>').addClass('column-uom required').text('Uom').appendTo(headerRow);
$('<th>').addClass('column-quantity required').text('Quantity').appendTo(headerRow);
$('<th>').text('Delete?').appendTo(headerRow);
// Add table body
var tableBody = $('<tbody>').appendTo(formsetTable);
data.forEach(function (component, index) {
var row = $('<tr>');
var codeCell = $('<td>');
var codeInput = $('<input type="text" maxlength="20" class="vTextField">');
codeInput.attr('name', 'production_components-' + index + '-code');
codeInput.val(component.code);
codeCell.append(codeInput);
var nameCell = $('<td>');
var nameInput = $('<input type="text" maxlength="100" class="vTextField">');
nameInput.attr('name', 'production_components-' + index + '-name');
nameInput.val(component.name);
nameCell.append(nameInput);
var uomCell = $('<td>');
var uomInput = $('<input type="text" maxlength="20" class="vTextField">');
uomInput.attr('name', 'production_components-' + index + '-uom');
uomInput.val(component.uom);
uomCell.append(uomInput);
var quantityCell = $('<td>');
var quantityInput = $('<input type="number" min="0" step="0.0001" required>');
quantityInput.attr('name', 'production_components-' + index + '-quantity');
quantityInput.val(component.quantity);
quantityCell.append(quantityInput);
var deleteCell = $('<td>');
var deleteButton = $('<button>').text('Delete');
deleteButton.addClass('delete-button');
deleteButton.on('click', function() {
// Handle delete button click
row.remove();
});
deleteCell.append(deleteButton);
row.append(codeCell, nameCell, uomCell, quantityCell,deleteCell);
formsetTable.append(row);
});
}
});
})(jQuery);
views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from .models import BillOfMaterials
@csrf_exempt
def ajax_view(request):
if request.method == 'POST':
production_name = request.POST.get('name')
production_quantity = request.POST.get('quantity')
bill_of_materials = BillOfMaterials.objects.filter(name=production_name).first()
if bill_of_materials:
child_components = bill_of_materials.child_components.all()
updated_components = []
for component in child_components:
if bill_of_materials.quantity == production_quantity:
updated_quantity = float(component.quantity)
else:
updated_quantity = float(component.quantity) * (float(production_quantity) / float(bill_of_materials.quantity))
updated_quantity = format(updated_quantity, '.4f')
updated_components.append({
'id': component.id,
'code': component.code,
'name': component.name,
'uom': component.uom,
'quantity': updated_quantity
})
return JsonResponse(updated_components, safe=False)
return JsonResponse([], safe=False)urls.py
from django.urls import path
from .views import ajax_view
urlpatterns = [
path('ajax/', ajax_view, name='ajax_view'),
]PDF export functionality
Step 1: Install Required Packages
First, you need to install WeasyPrint, a library that converts HTML and CSS into PDFs.
Run the following command to install WeasyPrint:
pip install weasyprintStep 2: Create a Django Project and App (if you haven’t already)
If you don’t already have a Django project and app set up, follow these steps:
- Create a new Django project:
django-admin startproject company_report_project
cd company_report_project
- Create a new app:
python manage.py startapp company
Add the app to INSTALLED_APPS in settings.py:
INSTALLED_APPS = [
# other apps
'company',
]
Step 3: Create the Company Model
Now, define the Company model in the company/models.py file.
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=255)
address = models.CharField(max_length=255, blank=True, null=True)
is_active = models.BooleanField(default=True)
subscription = models.CharField(max_length=100, blank=True, null=True) # Simple string field for subscription
employee_limit = models.IntegerField(default=10)
def __str__(self):
return self.name
After defining the model, run the following commands to create the database table:
python manage.py makemigrations
python manage.py migrate
Step 4: Register the Company Model in the Admin
In company/admin.py, register the Company model to make it accessible in the admin panel.
from django.contrib import admin
from .models import Company
@admin.register(Company)
class CompanyAdmin(admin.ModelAdmin):
list_display = ('name', 'address', 'is_active', 'employee_limit', 'subscription')
This will allow you to manage Company data from the Django admin interface.
Step 5: Add the Export to PDF Functionality
Now we will add the PDF export button in the Django admin panel that will allow users to export selected companies to PDF.
- Create a view function for exporting selected companies as a PDF:
In company/admin.py, modify the CompanyAdmin class to include an export function using WeasyPrint.
from django.template.loader import render_to_string
from django.http import HttpResponse
from weasyprint import HTML
@admin.register(Company)
class CompanyAdmin(admin.ModelAdmin):
list_display = ('name', 'address', 'is_active', 'employee_limit', 'subscription')
def export_as_pdf(self, request, queryset):
# Context for the HTML template
context = {
'companies': queryset
}
# Render the HTML template to a string
html_string = render_to_string('company_report.html', context)
# Convert the HTML string to a PDF using WeasyPrint
pdf_file = HTML(string=html_string).write_pdf()
# Create a response object and specify the PDF file's headers
response = HttpResponse(pdf_file, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="company_report.pdf"'
return response
export_as_pdf.short_description = "Export Selected Companies as PDF"
# Add the export button to the admin actions
actions = ['export_as_pdf']
Step 6: Create the HTML Template for the Report
Now, create the HTML template that will be used to generate the PDF report.
- Inside the
companyapp, create a directory calledtemplates. - Inside
templates, create another directory calledcompanyand place the following HTML file inside it:company_report.html.
Here’s the structure:
company/
└── templates/
└── company/
└── company_report.html
company_report.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Company Report</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.header {
text-align: center;
margin-bottom: 40px;
}
.header h1 {
font-size: 24px;
margin: 0;
}
.header p {
font-size: 14px;
color: #666;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 30px;
}
table th, table td {
border: 1px solid #ddd;
padding: 8px;
text-align: center;
}
table th {
background-color: #f2f2f2;
font-weight: bold;
}
.footer {
text-align: center;
font-size: 12px;
color: #777;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="header">
<h1>Company List</h1>
<p>This report contains information about registered companies.</p>
</div>
<table>
<thead>
<tr>
<th>Company Name</th>
<th>Address</th>
<th>Active</th>
<th>Subscription</th>
<th>Employee Limit</th>
</tr>
</thead>
<tbody>
{% for company in companies %}
<tr>
<td>{{ company.name }}</td>
<td>{{ company.address|default:"N/A" }}</td>
<td>{{ "Yes" if company.is_active else "No" }}</td>
<td>{{ company.subscription|default:"No Subscription" }}</td>
<td>{{ company.employee_limit }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="footer">
<p>Generated by the Company Management System</p>
</div>
</body>
</html>
Step 7: Use the Admin Interface
- Start the Django development server:
python manage.py runserver
- o to the Django admin panel (
http://127.0.0.1:8000/admin/), log in, and navigate to the Companies section. - Select one or more companies and choose Export Selected Companies as PDF from the dropdown actions menu.
Step 8: Test the PDF Export
- After selecting companies and choosing the Export option, a PDF should be generated and downloaded with the selected company’s information.