Django Configuration
Django Configuration
1. Installation Django
 INSTALL THE VIRTUALENV IN SYSTEM:
    CMD  pip install virtualenv
 ACTIVATE THE DJANGO COMMAND ON VS CODE:
    djangoenv\Scripts\activate
 DEACTIVATE COMMAND:
    deactivate
 INSTALL DJANGO:
    pip install django
 CREATE FIRST PROJECT:
    django-admin startproject "Project name"
 AFTER INSTALLING CHANGE THE DIRECTORIES:
    cd vcs
 START OUR DEVLOPMENT SERVER BY RUNNING COMMOND:
    python manage.py runserver
 QUIT IN DJANGO SERVER:
    CTRL+C
                                 2. First App in Django
 CREATE AN APP:
    python manage.py startapp "App Name"
 ADD THE APP NAME IN SETTINGS.PY/INSTALLED APPS:
    'App name',
                            3. URL Section using html file
 ADD THE FUNCTION IN views.py FILES:
    from django.http import HttpResponse
def home(request):
 NOW CALL THE ABOVE FUNCTION IN OUR WEBSITE USING urls.py FILES:
    from home.views import *
urlpatterns = [
 NOW MOVE THE PEOPLES LIST IN OUR HTML FILE USING A CONTEXT KEYWORD:
    return render(request, 'home/index.html', context={'peoples': peoples}) (using this function we
     can add the backend data in template file home.html)
 NOW RENDER THE DATA IN HTML TEMPLATE:
    {{peoples}}
 NOW ADD THE TABLE IN HTML FILE:
    <table>
<tr>
<th>Sr. no.</th>
<th>Name</th>
<th>age</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
        </table>
 NOW ADD THE FOR LOOP IN view.py FILES:
    for people in peoples:
               print(people)
 RENDER THE view.py FOR LOOP IN HTML FILE:
    <table>
       <tr>
               <th>Sr. no.</th>
               <th>Name</th>
               <th>age</th>
       </tr>
       {% for people in peoples %}
       <tr>
               <td>{{forloop.counter}}</td>
               <td>{{people.name}}</td>
               <td>{{people.Age}}</td>
       </tr>
       {% endfor %}
       </table>
 ADD ONE MORE TR TAG NAMED CAN VOTE & AFTER GIVE THEM CONDITON.
 NOW WE CAN CREATE A IF..ELIF..ELSE LOOP: USING ONE VEGETABLE LIST
    IN HTML FILE:
    <td {% if people.Age < 18 %} style="background: red;" {% endif %}>
           {% if people.Age >= 18 %}
               👍
           {% else %}
               👎
            {% endif %}
       </td>
 NOW CREATE 2 MORE FILE & COPY PASTE CODE IN HTML FILE:
    CONTACT.HTML
    ABOUT.HTML
 NOW ADD THE VIEWS IN views.py FILE
    def contact_page(request):
               return render(request, 'home/contact.html')
      def about(request):
              return render(request, 'home/about.html')
 NOW ALSO ADD IN A URL IN urls.py FILE:
    path('contact/', contact_page, name= 'contact'),
      path('about/', about, name= 'about'),
 NOW CREATE A URL LINKS TO GO ON DIFFERENT PAGE IN HTML:
    Home.html
 <a href="/contact/">Contact</a>|
    <a href="/about">About</a>
    About.html
<a href="/">Home</a>|
    <a href="/contact">Contact</a>
    Contact.html
<a href="/">Home</a> |
    <a href="/about">About</a>
 NOW THE HTML BOILOR CODE IS REPEAT IN EVERY HTML FILE SO WE WILL REMOVE THE CODE &
   INHERIT WITH OTHER FILE:
 CREATE A NEW FILE IN TEMPLATE FOLDER NAMED base.html:
 COPY & PASTE THE HTML CODE WHICH CAN REPEAT ONE & MORE TIME:
     <!DOCTYPE html>
<html lang="en">
<head>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
rel="stylesheet"
     integrity="sha384-
T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
crossorigin="anonymous">
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Django tutorial</title>
  <style>
     table,
     th,
     td {
       border: 1px solid black;
     }
  </style>
</head>
<body>
  {% block content %}
  {% endblock %}
  <script>
    console.log("Hello World");
  </script>
</body>
</html>
 WE WRITE THE CODE BETWEEN BODY TAG TO INHERIT OTHER FILES:
     {% block content %}
       {% endblock %}
 NOW ADD THAT CODE IN HTML MAIN FILES LIKE(Index, Contact, About Files)
    <!-- inherit with base.html document -->
     {% extends 'base.html' %}
     {% block content %}
         def run_this_function():
                 print("Function Started")
                 time.sleep(1)
                 print("Function Executed")
   IF U WANT TO RUN THIS FUNCTION IN DJANGO THEN USE THE SHELL.
   WRITE RETURN TO IMPORT CODE IN SHELL. [Link]
   IF U WANT TO CHECK THE DATA LIKE U WANT TO CHECK SOME DATA THAT CAN CHECK IN SHELL.
   YOU CAN LEARN ABOUT MORE MODELS IN DEPTH IN THE GIVEN WEBSITE: [Link]
                                 7. CRUD Operations
 CRUD : Create, Read, Update, Delete
                            7.1 CREATE OPERATION
 LET’S CREATE A NEW MODELS IN MODELS.PY FILE.
    class Car(models.Model):
               car_name = models.CharField(max_length = 100)
               speed = models.IntegerField(default = 50)
 NOW CREATE A DATA FROM A CAR LIST.
    from home.models import *
       car = Car()
       car = Car(car_name = "Nexon" , speed = "120")
       car = Car(car_name = "XUV 700" , speed = "150")
       car.save()
 THIRD TRICK TO CREATE A OBJECT
    car_dict = {"car_name" : "Alto" , "speed" : 80}
 NOW MERGE ALL THE OBJECT USING COMMAND
    Car.objects.create(**car_dict)
                                     7.2 READ OPERATION
 RUN THE COMMAND TO PRINT THE CAR.
    Cars = Car.objects.all()
       Cars
 UNDERSTAND THE OBJECT NAME WE CAN CREATE A DEF METHOD IN MODELS FILE SO THE OBJECT
  WILL BE REPLACE.
    def __str__(self) -> str:
       return self.car_speed
 AFTER THAT PROCESS RUN THE COMMAND ON SHELL.
    Cars = Car.objects.all()
       Cars
 IF WE NEED TO PRINT ALL THE CAR DATA THEN WE CAN RUN THIS CODE.
    for car in cars:
               print(f"This Car name is {car.car_name} with high speed of {car.speed}")
 IF U WANT TO GET ONLY PARTICULAR CAR THEN WRITE THE CODE.
    car = Car.objects.get(id = 1)
       car
 FILTER METHOD: WHEN THE DATA DOES NOT MATCH IT WILL RETURN THE BLANK SPACE.
    car = Car.objects.filter(id = 10)
       car
       <QuerySet []>
                                       7.3 UPDATE OPRATION
 WE CAN UPDATE THE LIST USE OF 2 METHOD.
  1. USING GET METHOD
      car = Car.objects.get(id = 1)
      car.car_name = "Creta"
      car.speed = 200
      car.save()
      car
  2. USING FILTER METHOD
      car = Car.objects.filter(id = 1).update(car_name = "Verna")
      Car.objects.all()
                                      7.4 DELETE OPERATION
 RUN THE COMMAND TO DELETE THE PARITCULAR ITEMS IN LIST.
    Car.objects.get(id = 5).delete()
 IF YOU WANT TO DELETE ALL THE DATA IN LIST.
    Car.objects.all().delete()
                                    8. RECEIPE Project
 FIRST CREATE AN APP NAMED “VEG”.
    python manage.py startapp veg
 NOTE: MODELS CLASS NAME & VIEWS DEF NAME, BOTH ARE DIFFERENT IF U GIVE SAME
  NAME THEN RE PASS THE ATTRIBUTE ERROR.
 THEN CREATE A NEW MODEL IN VEG MODELS FILE.
    class Receipe(models.Model):
              receipe_name = models.CharField(max_length = 100)
              receipe_description = models.TextField()
              receipe_image = models.ImageField(upload_to='receipe')
 NOW ADD THE APP IN CORE FOLDERS SETTINGS.PY FILE.
    'veg',
 NOW RUN THE MAKEMIGRATIONS COMMAND
    python manage.py makemigrations
 NOW RETURN THE TEMPLATE IN VIEWS.PY FILE
    def receipes(request):
               return render(request, 'receipes.html')
 NOW CREATE A TEMPLATES FOLDER IN RECEIPES FOLDER & CREATE ONE FILE RECEIPES.HTML FILE
  THAT FOLDER.
 NOW INHERIT THE DATA OF base.html FILE
    {% extends 'base.html' %}
      {% block content %}
     {% endblock %}
 NOW GIVE THE URL OF RECEIPES PAGE IN urls.py FILE.
    from veg.views import *
                       receipe_image = request.FILES.get('receipe_image')
                       receipe_name = data.get('receipe_name')
                       receipe_description = data.get('receipe_description')
                               Receipe.objects.create(
                                      receipe_image = receipe_image,
                                      receipe_name = receipe_name,
                                      receipe_description = receipe_description,
                                      )
         STATIC_URL = '/static/'
         STATIC_ROOT = os.path.join(BASE_DIR,'staticfiles')
         STATICFILES_DIR = {
           os.path.join(BASE_DIR , "public/static")
         }
        urlpatterns = [
          path('admin/', admin.site.urls),
          path('receipes/', receipes, name='receipes')
        ]
        if settings.DEBUG:
           urlpatterns += static(settings.MEDIA_URL,
                        document_root=settings.MEDIA_ROOT)
        urlpatterns += staticfiles_urlpatterns()
 AFTER ADDING THAT U CAN ADD ANOTHER ITEM IN RECEIPE & U CAN SEE CREATE A NEW FOLDER
  NAMED PUBLIC & UR IMAGE WILL BE STORE IN THAT FOLDER.
 URL FILE IS USE TO GO TO MEDIA ROUTE & UNDERSTAND THE DJANGO. OR
 SETTING.PY IS USE TO CREATE STATIC DIR OR BIND DIR & UPLOAD ALL THE FILE IN THIS DIR.
 IF U WORK WITH BIG PROJECT TO DJANGO PROFILE CANT DUMP. CDN IS CONTENT DELEVIRY
  NETWORK, WE CAN UPLOAD DIRECTLY IN THAT PLACE.
 ACTUALLY, IF CREATE ANY APPLICATION THEN IT IS USE TO CDN FOR STORE & UPLOAD STATIC FILES
  BCZ OF FAST ACCESS OF APPLICATION.
 NOW ADD THE <IMG> TAG TO SEE THE IMAGE ON WEBSITE.
      <td><img src="/media/{{receipe.receipe_image}}" alt="" style="height: 100px;"></td>
 IF U WANT TO DELETE SOME RECEIPE THAN ADD THE <TH> & <TD> IN HTML FILE.
      <th scope="col">Actions</th>
 <td>
        <button class="btn btn-danger">Delete</button>
 </td>
 NOW CHANGE THE BUTTION NAME & ADD THE A HREF LINK TAG.
      <a href="" class="btn btn-danger">Delete</button>
 NOW CREATE A NEW ROUTE IN VIEWS.PY FOR HANDLE A DYNAMIC URLS.
      def delete_receipe(request, id):
      print(id)
      return HttpResponse("a")
 NOW REGISTER ON URLS.PY FILE.
      path('delete_receipe/<id>/', delete_receipe, name='delete_receipe'),
 HOW TO WORK DYNAMIC URLS IN DJANGO?
 WHEN A USER PASSES A UNIQUE ID WE WILL CREATE A DYNAMIC URL. IF WE CREATE A STATIC ID
  THEN ID WILL MISSED.
 USER GO ON DYNAMIC URL & CHECK THE URL, FOR CHECK THE URL WE PASS THE QUERYSET IN THAT
  QUERYSET ADMIN WILL SET IF QUERY WILL MATCHED THEN THAT CLICK ON DELETE BUTTON DELETE
  THAT ID OR ITEM IN LIST & REDIRECT THE PAGE.
     def delete_receipe(request, id):
{% endblock %}
          if request.method == "POST":
              data = request.POST
               receipe_image = request.FILES.get('receipe_image')
               receipe_name = data.get('receipe_name')
               receipe_description = data.get('receipe_description')
               queryset.receipe_name = receipe_name
               queryset.receipe_description = receipe_description
# FOR ADDING THE RECEIPE IMAGE, ADD ANOTHER LOGIC ON IMAGE ATTRIBUTE
               if receipe_image:
                   queryset.receipe_image = receipe_image
               queryset.save()
               return redirect('/receipes/')
   {% endblock %}
 NOW ADD THE LOGIN PAGE IN VIES.PY FILE & SET THE URLS IN URLS.PY FILE.
    views.py
def login_page(request):
    return render(request, 'login.html')
    urls.py
     path('login/', login_page, name='login_page'),
 CREATE REGISTER PAGE SAME AS ABOVE TECHNIC.
 ADD THE <P> TAG BOTH PAGES & GIVE TO LINK THE REGISTER & LOGIN.
    register.html
<P>
  Already have account <a href="/login/">Login</a>
</P>
    login.html
<P>
  Don't have account <a href="/register/">Register</a>
</P>
 LET’S ADD THE USER FIELD.
 DJANGO CAN AUTOMATICALLY GIVE THE FIELD FOR USR LET’S SEE.
 YOU CAN JUST CLICK(CTRL+MOUSE) THE User in Models.py file, NOW U CAN SEE THE ONE
  MODELS.PY PAGE ON U SCREEN & SEE THE USER PROPERTY.
     class User(AbstractUser):
     """
     Users within the Django authentication system are represented by this
     model.
   class Meta(AbstractUser.Meta):
       swappable = "AUTH_USER_MODEL"
 NOW CLICK ON ABSTRACTUSER & SEE THE ALL USER FIELD LIKE F_NAME, L_NAME.
 NOW ADD THE ALL USER RELATED FIELD IN OUR FILE.
   <div class="mb-3">
                <label for="exampleInputEmail1" class="form-label">First
   Name</label>
                <input type="text" class="form-control"
   id="exampleInputEmail1" aria-describedby="emailHelp">
           </div>
           <div class="mb-3">
                <label for="exampleInputEmail1" class="form-label">Last
   Name</label>
                <input type="text" class="form-control"
  id="exampleInputEmail1" aria-describedby="emailHelp">
           </div>
 ADD THE NAME FIELD IN INPUT TAG & GIVE A NAME ALL THE RELATED FIELD.
 NOW IMPORT THE MODEL & ADD THE IF CONDITION IN VIEWS.PY FILE SAME AS PREVIOUS TECH.
    from django.contrib.auth.models import User
     def register(request):
        if request.method == "POST":
         first_name = request.POST.get('first_name')
         last_name = request.POST.get('last_name')
         username = request.POST.get('username')
         password = request.POST.get('password')
         user = User.objects.create(
             first_name = first_name,
             last_name = last_name ,
             username = username,
             )
         # FOR ENYCRPT THE PASSWORD, CALL THE USER TO SET PASSWORD.
         user.set_password(password)
         user.save()
return redirect('/register/')
 LET’S CHECK THE REGSITER PAGE & ENTER THE DATA IN FIELD.
 U CHECK THE ENTERED DATA IN SHELL USING THE GIVEN COMMAND IN LINK.[Link]
 FOR IMPORT THE REGISTER DATA IN SHELL RUN THE COMMAND.
    from django.contrib.auth.models import *
    User.objects.all()
 NOW IF U ENTER THE SAME USERNAME THAN DJANGO PASSED THE UNIQUE CONSTRAINT ERROR
  BCZ OF THE USERNAME WILL ALWAYS A DIFFERENT.
 FOR CHECK THE SAME USERNAME ARE IN OR NOT IN FOR THAT WE CAN ADD THE QUERY IN
  VIEWS.PY FILE.
    user = User.objects.filter(username = username)
           if user.exists():
                  return redirect('/register/')
   NOW U WANT TO SHOW THE ERROR WHEN A SAME USERNAME ARE EXISTS.
   FOR THAT DJANGO GIVE A SOME MESSAGES IN THEIR SYTEM WE CAN SIMPLY IMPORT THE
    MESSAGES.[Link] in this link u can see the import message pack & add our views.py file.
      from django.contrib import messages
   AFTER IMPORTING THE MESSAGE PACK ADD THE CODE IN REGISTER ROUTE
      if user.exists():
                  messages.info(request, "Username already exists.")
                  return redirect('/register/')
   ANOTHER MESSAGE FOR ACCOUNT CREATED SUCCESSFULLY IN BELOW TO USER.SAVE().
      user.set_password(password)
           user.save()
           messages.info(request, "Account created Successfully")
           return redirect('/register/')
   FOR GET THE MESSAGE U ALSO ADD THE REQUEST IN YOUR REGISTER.HTML FILE.
      {% if messages %}
        <ul class="messages">
                 {% for message in messages %}
                 <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
                 {% endfor %}
        </ul>
        {% endif %}
   NOW ADD SOME BOOTSTRAP ALERT BOX IN DOCUMENT & CUSTMIZE THE CODE.
     {% if messages %}
           <!-- {{ message.tags }} -->
           <div class="alert alert-primary" role="alert">
               {% for message in messages %}
               {{ message }}
               {% endfor %}
           </div>
          {% endif %}
 NOW U CAN CHECK THE WEBSITE FOR SAME USERNAME & ANOTHER NEW USERNAME U CAN SEE
  THE MESSAGE.
 NOW CREATE SAME AS A LOGIN PAGE WHEN USER ENTER THE USERNAME OR PASSWORD IT CAN
  SEE THE ITEMS & ACCESS IT.
 IN THIS, PROCESS WE CAN ADD THE POST METHOD IN LOGIN ROUTE & APPLY A FILTER FOR A GET
  SAME USER NAME IN SYSTEM OR NOT.
    if request.method == "POST":
             username = request.POST.get('username')
                password = request.POST.get('password')
else:
   login(request, user)
   return redirect('/receipes/')
 IMP: ROUTE NAME & IN ELSE CONDITION NAME BOTH ARE DIFFERENT.
 CODE FOR LOGIN ROUTE FOR FULL LOGIN ACCESS.
def login_page(request):
    if request.method == "POST":
        username = request.POST.get('username')
        password = request.POST.get('password')
        if not User.objects.filter(username = username).exists(): #
exists(): it is a boolean value.
              messages.info(request, "Invalid Username")
              return redirect('/login/')
          user = authenticate(username = username, password = password)
          if user is None: # PASSWORD IS NOT MATCHED.
              messages.info(request, "Invalid Password")
              return redirect('/login/')
          else:
              login(request, user)
              return redirect('/receipes/')
      return render(request, 'login.html')
 ADD THE USERNAME IN RECIEPES PAGE U CAN ADD THE REQUEST IN RECEIPES.HTML FILE.
    {{request.user}}
       {{request.first_name}}
 CREATE A NEW LOG OUT PAGE IN views.py FILE ADD THE IMPORT METHOD LOGOUT.
    from django.contrib.auth import authenticate, login, logout
def logout_page(request):
     logout(request)
     return('/login/')
 ADD THAT ROUTE IN urls.py FILE.
  FOR LOGOUT WE CAN ADD THE LOG OUT BUTTON IN NAVBAR USING BOOTSTRAP IN BASE.HTML
  FILE.[Link]
    <nav class="navbar dark p-3 bg-danger shadow-lg">
            <div class="container-fluid">
                <a class="navbar-brand">Navbar</a>
                <form class="d-flex" role="search">
                    {% if request.user.is_authenticated %}
                    <a href="/logout/" class="btn btn-success" type="submit">Log
Out</a>
                      {% else %}
                      <a href="/login/" class="btn btn-success"
type="submit">Login</a>
                      {% endif %}
               </form>
         </div>
    </nav>
    In above code we also mention the if..else condition in that the condition is if user is
      authenticated then it will get a login & see the logout button but else if user is noe logged in
      then it will redirect the login page.
 BUT THE ONE PROBLEM IS THAT, ANYONE CAN ACCESS THE RECEIPES PAGE FOR THAT WE CAN
  ADD THE DECORATOR METHOD AUTHENTICATE CONDITION LIKE LOGIN REQUIRED.
    from django.contrib.auth.decorators import login_required
 AND U WANT TO ACCESS ANY PAGE OF LOGIN REQUIRED THAN U CAN ADD CODE ABOVE THE
  ROUTE & GIVE THE URL OF LOGIN PAGE.
    @login_required(login_url="/login/")
      def receipes(request):
                                 10. Master Django ORM
 SUPPOSE WE HAVE ENTER THE COUNT FUNCTIONALLYTIES IN MODELS
    receipe_view_count = models.IntegerField(default= 1)
 NOW MIGRATE THE MODELS & OPEN THE SHELL IN CMD.
 IMPORT THE ALL THE RECEIPES.
    from veg.models import *
 CHECK THE HOW MANY RECEIPES IN SYSTEM.
    veg = Receipe.objects.all()
 NOW GIVE THE RANDOM NUMBER FOR THAT IMPORT THE RANDOM IN SHELL.
    import random
 ADD THE FOR CONDITION FOR GIVING THE RANDOM NUMBERS USING COUNT MODEL.
    for vege in veg:
       vege.receipe_view_count = random.randit(10, 100)
       vege.save()
 NOW CHECK THE RECEIPE ALL RECEIPES PASS THE DIFFRENET NUMBER.
    veg[0].receipe_view_count
 NOW THAT DATA HOW WE MANAGE IN ORDERING OR SORT BY.
       veg = Receipe.objects.all().order_by('receipe_view_count') # it can pass the assending order
          set.
       veg = Receipe.objects.all().order_by('-receipe_view_count') # it can pass the desending order
          set.
 IF U HAVE A BIG DATA THAN APPLY THE LIMIT.
       veg = Receipe.objects.all().order_by('-receipe_view_count')[0:1]
 IF U WANT TO FILTER SOME RECEIPE FROM THEIR COUNT BASE.
       veg = Receipe.objects.filter(receipe_view_count__gte = 45) #__gte means greater than 45
       veg = Receipe.objects.filter(receipe_view_count__lte = 45) #__lte means less than 45
 LETS CREATE A SOME NEW MODELS FOR.
class Department(models.Model):
     department = models.CharField(max_length = 100)
    class Meta:
        ordering = ['department'] #Meta class for department can see
sequence vise
class StudentID(models.Model):
    student_id = models.CharField(max_length = 100)
class Student(models.Model):
    department = models.ForeignKey(Department, related_name ="depart",
on_delete=models.CASCADE)
    student_id = models.OneToOneField(StudentID, related_name ="studentid",
on_delete=models.CASCADE)
    student_name = models.CharField(max_length = 100)
    student_email = models.EmailField(unique=True)
    student_age = models.IntegerField(default=18)
    student_address = models.TextField()
      class Meta:
           ordering =['student_name']
           verbose_name = "student"
   NOW CREATE A SUPERUSER IN DJANGO ADMIN.
         python manage.py createsuperuser
   REGISTER THE ADMIN IN ADMIN.PY FILE.
         admin.site.register(Receipe)
           admin.site.register(StudentID)
           admin.site.register(Student)
           admin.site.register(Department)
   NOW LOGIN ON DJANGO ADMINISTRATOR USING USERNAME & PASSWORD.
   FOR, ADD THE LARGE DATA WE ADD SOME PYTHON FEATURES “FAKERS” LIBRARY[Link].
   CREATE A NEW FILE NAMED “SEED.PY” & ADD THE FAKER CODE IN THIS FILE.
      from faker import Faker
      fake = Faker()
      from .models import *
      import random
   CREATE A NEW FUNCTION FOR ADD SOME FAKE DATA & GIVE THE NUMBER TO ENTER THE DATA
    OF THAT COUNT.
   NOW ITTRATE THE FOR IN RANGE.
      def seed_db(n=10)->None:
      for i in range(0, n):
        [1, 2, 3, 4]
        department_objs = Department.objects.all()
        randome_index = random.randint(0, len(department_objs)) # FOR ADDING
THE RANDOM INDEX NUMBER
        department = department_objs[randome_index]
        student_id = f'STU-0{random.randit(100, 900)}' # FOR ADDING A RANDOM
NUMBER IMPORT THE RANDOM FUNCTION
          student_name = fake.name()
          student_email = fake.email()
          student_age = random.randint(20, 30)
          student_address = fake.address()
 LET’S CREATE A OBJECT FOR STUDENTS ID.
    student_id_obj =StudentID.objects.create(student_id = student_id)
 NOW CREATE A OBJECT FOR STUDENTS DETAIL.
    student_obj = Student.objects.creat()
          department = department,
          student_id = student_id_obj,
          student_name = student_name,
          student_email = student_email,
          student_age = student_age,
          student_address = student_address,
 NOW USE THE “SOURCERY” EXTENSIONS FOR REPLACE THE INDEX ERROR JUST RIGHT CLICK ON
  FOR IN RANGE & 1ST OPTION U WILL SHOW THE REPLACE INDEX CLICK ON THAT.
 BCZ OF A CODE IS NOT BLOCKED, CAN ADD THE TRY EXPECTION IN FOR IN RANGE.
 SUPPOSE WE WANT TO AVERAGE DATA FOR STUDENTS AGE USING AGGREGATE FUNCTION.
    from django.db.models import *
    from veg.models import *
    Student.objects.aggregate(Avg('student_age'))
    Student.objects.aggregate(Max('student_age'))
    Student.objects.aggregate(Min('student_age'))
    Student.objects.aggregate(Sum ('student_age'))
 NOW WE WANT TO BETWEEN THE AGE DATA USING ANNOTATE FUNCTION.
   from django.db.models import *
   from veg.models import *
   student = Student.objects.values('student_age').annotate(Count('student_age'))
   student
   student = Student.objects.values('department').annotate(Count('department'))
   student
 NOW U WANT TO MULTIPLE DATA GET OF STUDENTS.
    student = Student.objects.values('department', 'student_age').annotate(Count('department'),
      Count('student_age')).values_list
    student
                              13. Students Report Card
 FIRST CREATE TWO MODELS IN MODELS.PY FILE FOR STUDENTS SUBJECT & MARKS DATA.
   class Subject(models.Model):
              subject_name = models.CharField(max_length = 100)
   class StudentMarks(models.Model):
              student = models.ForeignKey(Student, related_name="studentmarks",
              on_delete=models.CASCADE)
              subject = models.ForeignKey(Subject, on_delete= models.CASCADE)
              marks = models.IntegerField()
 IN DATABASE PARTICULAR STUDENT MARKS ARE UNIQUE, IT MEANS ONSE STUDENT DO NOT GET
  2 TIMES MARKS IN 1 SUBJECT FOR THAT WE CAN ADD THE UNIQUE METHOD IN META CLASS FOR
  BELOW SUBJECTMARKS CLASS.
   class Meta:
              unique_together = ['student' , 'subject']
 NOW WE CAN ALSO ADD ABOVE THAT DEF FUNCTION USING F STRING.
    def __str__(self) -> str:
              return f'{self.students.student_name} {self.subject.subject_name}'
 except Exception as e:
   print(e)
 FOR DISPLAYING THE SUBJECT & MARKS AT A ONE DISPLAY FOR THAT WE ADD THE CLASS IN
   ADMIN.PY.
     class SubjectMarkAdmin(admin.ModelAdmin):
               list_display = ['student', 'subject', 'marks']
        admin.site.register(SubjectMarks , SubjectMarkAdmin)
 FOR SEE THE SUBJECT NAME WE CAN RETURN THE DEF FUNCTION IN BELOW THE SUBJECT CLASS
  IN MODELS.
    def __str__(self) -> str:
       return self.subject_name
 NOW WE CAN GET THE DATA IN FRONTEND FROM DJANGO ADMIN TO FRONTEND PAGE.
    FIRST WE CAN ADD THE LOGIC IN VIEWS.PY PAGE.
    def get_student(request):
       queryset = Student.objects.all()
       return render(request, 'report/students.html' , {'queryset' : queryset})
 NOW CREATE A NEW FOLDER IN TEMPLATE FOLDER NAMED REPORT & IN THAT CREATE A NEW
  FILE NAMED STUDENTS.HTML
 REGISTER IN URLS.PY FILE.
 NOW CREATE A SIMPLE TABLE IN STUDENTS.HTML FILE & ADD THE CODE FOR DISPLAYING THE
  STUDENTS.
    {% extends 'base.html' %}
   {% block content %}
    def get_student(request):
      queryset = Student.objects.all()
      paginator = Paginator(queryset, 25) # Show 25 contacts per page.
      page_number = request.GET.get("page" , 1)
      page_obj = paginator.get_page(page_number)
      print(page_obj)
      return render(request, 'report/students.html' , {'queryset' : page_obj})
     this record only for 1st page, for view the 2nd page code here we can add some bootastrap ui
        code.
     <nav aria-label="Page navigation example">
         <ul class="pagination">
           {% if queryset.has_previous %}
           <li class="page-item"><a class="page-link" href="?page=1">« first</a></li>
           <li class="page-item"><a class="page-link" href="?page={{ queryset.previous_page_number
    }}">previous</a>
           </li>
           {% endif %}
           <span class="current">
             Page {{ queryset.number }} of {{ queryset.paginator.num_pages }}.
           </span>
           {% if queryset.has_next %}
           <li class="page-item"><a class="page-link" href="?page={{ queryset.next_page_number
    }}">next</a></li>
           <li class="page-item"><a class="page-link" href="?page={{ queryset.paginator.num_pages
    }}">last »</a>
           </li>
           {% endif %}
         </ul>
       </nav>
    </div>
    {% endblock %}
 NOW ADD THE FILTER ON RECORD.
    if request.GET.get('search'):
   search = request.GET.get('search')
   queryset = queryset.filter(student_name__icontains = search)
 FOR ADDING THE SEARCH BUTTON
    <form>
   <div class="row">
     <div class="col-md-6">
       <input class="form-control" placeholder="search">
     </div>
      <div class="col-md-6">
        <button class="btn btn-success">Search</button>
      </div>
    </div>
  </form>
 NOW ADD THE ALL DATA ARE FILTERED FOR THAT WE CAN ADD OR CONDITON.
     from django.db.models import Q
     if request.GET.get('search'):
    search = request.GET.get('search')
    queryset = queryset.filter(
      Q(student_name__icontains = search) |
      Q(department__department__icontains = search) |
      Q(student_id__student_id__icontains = search) |
      Q(student_email__icontains = search)
      )
 GENERATE THE REPORT CARD. (EX., Rank, Marks,Etc…)
 SUPPOSE ANYONE CLICK ON STUDENTS ID THAN THEY GET ALL THE MARKS THE STUDENTS.
    LET’S CREATE A ONE PAGE FOR SEEING THE MARKS OF STUDENTS.
    def see_marks(request, student_id): # for using student_id see the marks
      queryset = SubjectMarks.objects.filter(student__student_id__student_id = student_id)
      return render(request , 'report/see_marks.html', {'queryset' : queryset})
 NOW ADD ROUTE IN URLS.
 NOW CREATE A LINK IN HTML FILE IN THE STUDENT_ID TD TAG.
    <td>
              <a href="/see-mark/{{student.student_id}}">
                      {{student.student_id}}
              </a>
      </td>
 NOW SUPPOSE U WANT TO CHANGE THE ROUTE NAME IN URLS FOR THAT U CAN ALSO CHANGE
  THE NAME IN ALL FILES IT’S CALLED DEPENDANCY, IN A BIG DATA WE CAN SET THE DEPENDANCY
  THAT AUTOMATE CHANGE THE ROUTE NAME IF U ONCE CHANGED.
  FOR THAT U CAN USE DJANGO URLS.
     <td>
               <a href="{% url 'see_marks' student.student_id %}">
                       {{student.student_id}}
               </a>
      </td>
 NOW CREATE A NEW FILE SEE_MARKS.HTML. ADD THE SEE MARKS LOGIC CODE IN TABLE, APPLY IF
  CONDITION & ADD THE MARKS.MARKS CONDITION.
    {% extends 'base.html' %}
{% block content %}
<div class="container mt-5">
    <!-- TABLE FOR THE STUDENTS DATA -->
    <table class="table table-striped">
         <tbody>
               {% for marks in queryset %} <!-- IMPORTING THE STUDENTS IN
queryset -->
               <tr>
                     <th scope="row">{{forloop.counter}}</th> <!-- FOR LOOP
COUNTER FOR AUTOMATED NUMBER -->
                     <td>
                          <b>{{marks.subject.subject_name}}</b> <!--ADD THE
SUBJECT NAME OF STUDENTS-->
                     </td>
                    <td>{{marks.marks}}</td>
               </tr>
               {% endfor %}
         </tbody>
    </table>
</div>
{% endblock %}
 NOW WE CAN ADD THE RANK DISPLAYING CODE.
    HTML CODE
       <h4>Rank :</h4>
       <h4>Total : {{total_marks.total_marks}}</h4>
 NOW ADD THE AGGREGATE FUNCTION FOR TOTAL IN VIEWS.PY
    total_marks = queryset.aggregate(total_marks = Sum('marks'))
      print(total_marks)
 ADD THE total_marks IN RETURN FUNCTION.
 GENERATE THE STUDENTS RANK.
 FOR SORTING THE MARKS USING ANNOTATE FUNCTION.
    ranks = Student.objects.annotate(marks = Sum('studentmarks__marks')).order_by('-marks' , '-
      student_age')
      for rank in ranks:
              print(rank.marks)
 NOW ADD THE CODE FOR DISPLAY THE RANK IN VIEW.PY
     current_rank = -1
  ranks = Student.objects.annotate(marks = Sum('studentmarks__marks')).order_by('-marks' , '-
student_age') #ANNOTATE FUNCTION FOR ORDER BY THE STUDENTS MARKS
  i=1
  for rank in ranks:
    if student_id == rank.student_id.student_id:
       current_rank = i
       break
    i=i+1
 ADD THE CURRENT_RANK FUNCTION IN SEE_MARKS FILE FOR DISPLAYING THE RANK.
 BUT THIS TRICK IS WRONG BCZ OF ITS TIME CONSUMING PROCESS,
 FOR THAT WE CAN CREATE A NEW MODEL IN THAT WE CAN STORE ALL THE RANKS OF STUDENT &
    WORK IT WITH.
      class ReportCard(models.Model):
          student = models.ForeignKey(Student, related_name="studentreportcard",
          on_delete=models.CASCADE)
          student_rank = models.IntegerField()
          date_of_report_card_generation = models.DateField(auto_now_add = True)
 MIGRATIONS APPLY.
 ADD SCRIPTS FOR GENERATING THE REPORT CARD IN SEED FILE.
      def generate_report_card():
  current_rank = -1
  ranks = Student.objects.annotate(marks = Sum('studentmarks__marks')).order_by('-marks' , '-
student_age')
  i=1
  for rank in ranks:
     print(rank)
     ReportCard.objects.create(
        student = rank,
        student_rank = i
      )
     i=i+1
 NOW ADD THE UNIQUE TOGETHER IN META CLASS IN MODEL FILE.
      class Meta:
                  unique_together = ['student_rank', 'date_of_report_card_generation']
 NOW REGISTER IN ADMIN OR LIST DISPLAY THE FUNCTION AFTER THAT WE CAN DISPLAYING THE
    TOTAL MARKS FOR THAT WE CAN ADD SOME CODE IN ADMIN SITE.
      class ReportCardAdmin(admin.ModelAdmin):
  list_display = ['student', 'studnet_rank', 'total_marks' ,'date_of_report_card_generation']
  def total_marks(self, obj): # total_marks key are not available for that we can add the custom method.
      subject_marks = SubjectMarks.objects.filter(student = obj.student)
      return subject_marks.aggregate(makrs = Sum('marks'))
  admin.site.register(ReportCard , ReportCardAdmin)
 NOW ADD THE ORDERING FOR THAT WE CAN ADMIN FILE ABOVE ADD DEF TOTAL MARKS.
    ordering = ['-student_rank']
 NOW ADD THE RANK IN FRONTEND FOR THAT ADD IN HTML FILE & REMOVE THE RANK METHOD
  IN VIEWS FILE.
    <h4>Rank : {{queryset.first.student.studentreportcard.first.student_rank}}</h4>
 NOW SAME AS ADD THE DORG.
                                  14. Custom User Model
 WHAT IS CUSTOM USER MODEL?
     Users within the Django authentication system are represented by this model. Username and
      password are required. Other fields are optional.
 WHAT IS ABSTRACTUSER?
     An abstract base class implementing a fully featured User model with admin-compliant
      permissions.
 DIFFRENCE BETWEEN ABSTRACTUSER CLASS & ABSTRACTBASEUSER?
    ABSTRACTUSER : In this class we can use django field & also add new field. We can combine
       both models & create a new model.
    ABSTRACTBASEUSER : If u want to start scratch or fully independent than u can use this class. U
       have only password & usernamee field in this class.
 NOW LETS CREATE A NEW APP NAMED “account” & REGISTER IN SETTINGS.PY FILE.[Link]
 LET’S IMPORT THE ABSTRACTUSER MODELS & CREATE A CLASS.
    from django.contrib.auth.models import AbstractUser
        class CustomUser(AbstractUser):
           phone_number = models.CharField(max_length = 12, unique=True)
           user_bio = models.CharField(max_length = 75)
           user_profile_image = models.ImageField(upload_to="profile")
         # ADD MANUALLY USERFEILD IN WEBSITE
         USERNAME_FIELD = 'phone_number' # WHAT U WANT TO LOGIN TIME ADD
         REQUIRED_FIELDS = []
   ADD THE MODEL MANAGER.
   FOR THAT WE CAN CREATE A NEW FILE MANAGER.PY & ADD BACKEND CODE FOR UNDERSTAND
    THE WEBSITE WHAT WE PASSED.
   NOW ADD TH BASE USER MANAGER IN FILE
      from django.contrib.auth.base_user import BaseUserManager
   NOW U WORK WITH THOSE IN DJANGO MOST OF THAT ARE BUILT IN WE CAN ONLY MODIFY THE
    CLASSES.
   NOW ADD A CREATE USER MATHOD IN USERMANAGER CLASS & PASS THE SELF PERAMETER.
      class UserManager(BaseUserManager):
                def create_user(self, phone_number, password = None, **extra_fields):
                         if not phone_number: # if condition for if not enter the phone number .
                                  raise ValueError("Phone Number Is Required")