create views.py to administration page - django

I need to make a page that can save a lot of students information for example when we want to add a new user/student we should enter some required field..actually I can add and save a name,last name,NO, etc...but I can't save a many lessons for one student like this picture.
my page
what I want is a view for my project . I try a lot Algorithm but I can't save to data base / admin page.
my admin.py
from django.contrib import admin
from .models import Students
class StudentsAdminInline(admin.TabularInline):
model =Students
class StudentsAdmin(admin.ModelAdmin):
list_display = ["__str__","o_no","f_name","l_name","University","date","timestamp","update"]
inlines = [StudentsAdminInline]
admin.site.register(Students)
my model.py
from django.db import models
class Students (models.Model):
email=models.EmailField()
f_name=models.CharField(default="",max_length=50)
l_name = models.CharField(default="",max_length=50,blank=False)
o_no=models.CharField(default="",null=False,max_length=50)
University=models.CharField(default="",max_length=50)
date=models.DateField(editable=True,null=True)
timestamp=models.DateTimeField(auto_now_add=True,auto_now=False)
update=models.DateTimeField(auto_now_add=False,auto_now=True)
def __str__(self):
return '{}'.format(self.id)
class Student (models.Model):
student=models.ForeignKey(Students,related_name='items')
Lessons=models.CharField(default="",max_length=50,blank=False)
Code=models.DecimalField(max_digits=2, decimal_places=1,null=True)
Success=models.CharField(default="",max_length=50,blank=False)
def __str__(self):
return '{}'.format(self.id)
my forms.py
class students_form_admin(forms.ModelForm):
class Meta:
model=Students
fields=["__str__","o_no","f_name","l_name","University","date","timestamp","update"]
class student_form_admin(forms.ModelForm):
class Meta:
model=Student
fields=["Lessons","Code","Success"]

You will need to use Django Formsets. Take a loot at Django Formsets.
Or if you want to use only django admin, you should change your code to:
admin.py:
from django.contrib import admin
from .models import Student, Lesson
class StudentAdminInline(admin.TabularInline):
model =Lesson
#admin.register(Student)
class StudentAdmin(admin.ModelAdmin):
list_display = ["__str__","o_no","f_name","l_name","University","date","timestamp","update"]
inlines = [StudentAdminInline]
models.py:
from django.db import models
class Student (models.Model):
email=models.EmailField()
f_name=models.CharField(default="",max_length=50)
l_name = models.CharField(default="",max_length=50,blank=False)
o_no=models.CharField(default="",null=False,max_length=50)
University=models.CharField(default="",max_length=50)
date=models.DateField(editable=True,null=True)
timestamp=models.DateTimeField(auto_now_add=True,auto_now=False)
update=models.DateTimeField(auto_now_add=False,auto_now=True)
def __str__(self):
return '{}'.format(self.id)
class Lesson (models.Model):
student=models.ForeignKey(Student,related_name='items')
name=models.CharField(default="",max_length=50,blank=False)
Code=models.DecimalField(max_digits=2, decimal_places=1,null=True)
Success=models.CharField(default="",max_length=50,blank=False)
def __str__(self):
return '{}'.format(self.id)
forms.py:
from .models import Student, Lesson
class students_form_admin(forms.ModelForm):
class Meta:
model=Student
fields=["__str__","o_no","f_name","l_name","University","date","timestamp","update"]
class student_form_admin(forms.ModelForm):
class Meta:
model=Lesson
fields=["Lessons","Code","Success"]

Alright, so I'm going to suggest that you read through how to create a view. The Django website has a lot of information that is incredible helpful. Here is the documentation for creating views.
As for saving to a database. Here is the documentation on setting up and using databases with your project. This link will show you how to use models and objects to save data from your view.
The Django website has all kinds of information that can help you.

Related

how to render two forms in one template using a class based view

I'm using django's built-in User model, but I also have my own Account model which extends it:
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
age = models.IntegerField(blank=True)
location = models.CharField(max_length=255, blank=True)
experience = models.TextField(blank=True)
in my admin.py file:
class AccountInline(admin.StackedInline):
model = Account
can_delete = False
verbose_name_plural = 'Accounts'
class CustomUserAdmin(UserAdmin):
inlines = (AccountInline,)
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
I want it to be that when a User registers they enter this information in, but my issue is getting both the UserForm and AccountForm in the same template/view.
As of now this is my registration view:
class UserRegistration(generic.CreateView):
form_class = RegisterForm
template_name = 'registration/registration.html'
def form_valid(self, form):
user = form.save()
form.registration_notification()
login(self.request, user, backend='django.contrib.auth.backends.ModelBackend')
return redirect(self.request.GET.get('next'))
How do I add my AccountForm to this view as well so that I can render both in the template and submit with one button. I've seen people do it with a function based view but is there a way to do it with a class-based view?
I also want the same idea for my UpdateView where a User can update User information, but also Account information. I assume it would follow the same logic.
You can use a Custom user model "Extend AbstractUser" since you want to add extra fields and add as many other fields as you want in a single model and avoid making extra queries to the database.
From Django documentation :
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
field 1
field 2
forms.py
from django.contrib.auth.forms import UserCreationForm
from myapp.models import User
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = User
fields = UserCreationForm.Meta.fields + ('custom_field',)
You can read more here

Filtering the View Based on User Custom Permission

I have 2 Models, one for a list of Courses and the other with the list of Enrollments for each User.
The Enrollment Table is currently structured to have only 1 record per student. There is a ManytoManyField in the Enrollment Table that allows me to add multiple courses for each Student.
I want to ensure that when the Student Logs in they only see Courses they have enrolled for. I can't figure out as to what query in the view is most appropriate to achieve this.
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Course(models.Model):
title = models.CharField(max_length=255)
description = models.TextField()
created_dt = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Enrollment(models.Model):
student = models.ForeignKey(User,on_delete=models.CASCADE)
course = models.ManyToManyField(Course)
def __str__(self):
return f"{self.student}'s Enrollments"
views.py
from django.shortcuts import render,get_object_or_404
from django.http import HttpResponse
from .models import Course,Step,Enrollment
from django.http import Http404
from django.contrib.auth.decorators import login_required
#login_required
def course_list(request):
#courses = Course.objects.all()
courses = Course.objects.filter(id in Enrollment.objects.filter(student=request.user))
return render(request,"courses/course_list.html",{'courses':courses})
I'm not sure the modeling of Enrollment makes much sense here, since basically you here create an extra table. It would make more sense to see Enrollment itself as a many-to-many relation between the Course and the User, like:
from django.contrib.auth import get_user_model
class Course(models.Model):
title = models.CharField(max_length=255)
description = models.TextField()
created_dt = models.DateTimeField(auto_now_add=True)
enrollment = models.ManyToManyField(get_user_model())
def __str__(self):
return self.title
If you later want to specify some extra properties per (course, user) tuple, you can specify the through parameter [Django-doc].
We can then obtain the list of courses with:
#login_required
def course_list(request):
courses = Course.objects.filter(enrollment=request.user)
return render(request,"courses/course_list.html", {'courses':courses})
If you keep using the original modeling, we can filter with:
#login_required
def course_list(request):
courses = Course.objects.filter(enrollment__student=request.user)
return render(request,"courses/course_list.html", {'courses':courses})
but this modeling is making things a bit "over complex".
Note: if you refer to the user model, it is advisable to use the get_user_model [Django-doc] function instead of User directly, since if you later implement a customer user model, then you will have a hard time changing everything.

Why it throws an error? `forms.py Cannot import model from models.py`

I am trying to use django forms. but whenever I try to import a Design model from models.py , I keep getting
cannot import name Design
Here is my forms.py
from django import forms
from .models import Design
class NewDesign(forms.ModelForm):
class Meta:
model = Design
fields = ['category', 'designImage']
Here is my models.py
from django.db import models
class Design(models.Model):
user=models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, related_name='design_category', on_delete=models.CASCADE)
designImage=models.ImageField()
timeuploaded=models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.user)
I KEEP GETTING IMPORT ERROR
ImportError:cannot import name 'Design'
Both models.py and forms.py are inthe same App folder. I don't know why it is not working but it should work....Any help will be appreciated . Thanks
error massege image
project structure
both models.py andd forms.py are in the same directory..have worked with forms before but dont understand why not working now...Thanks
You have a circular import, because forms.py has
from .models import Design
and models.py has
from . import forms
You shouldn't normally have to import forms inside your models.py, so if you aren't using it, just remove the import.

How to override default display values for a select field for foreign keys in the Django Admin?

I'm creating models, where each model should be related with a user, like this:
class Item(models.Model):
user = models.ForeignKey(User)
But then in the Django Admin, for an Item, it shows a select field with all the users listed by their usernames. In addition to their usernames, I also need to display each user's first_name and last_name.
How can all three fields be displayed together within that select list in the Django Admin interface?
You need to create custom Form for this and set form attribute in your ModelAdmin.
In that Form you will need to override form field type of user field on model to custom ModelChoiceField.
ModelChoiceField has a method called label_from_instance, you need to override that to get full name.
Example code
######################################
## models.py ##
######################################
from django.db import models
from django.contrib.auth.models import User
class Item(models.Model):
user = models.ForeignKey(User)
name = models.CharField("name", max_length=60)
def __unicode__(self):
return self.name
######################################
## forms.py ##
######################################
from django import forms
from django.contrib.auth.models import User
from .models import Item
class CustomUserChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return obj.get_full_name()
class ItemForm(forms.ModelForm):
user = CustomUserChoiceField(queryset=User.objects.all())
class Meta:
model = Item
######################################
## admin.py ##
######################################
from django.contrib import admin
from .models import Item
from .forms import ItemForm
class ItemAdmin(admin.ModelAdmin):
form = ItemForm
admin.site.register(Item, ItemAdmin)
Source Code Reference
https://github.com/django/django/blob/1.4.5/django/forms/models.py#L948
Related Questions
Django admin - change ForeignKey display text
Django forms: how to dynamically create ModelChoiceField labels
Change Django ModelChoiceField to show users' full names rather
than usernames
Django show get_full_name() instead or username in model form
django: customizing display of ModelMultipleChoiceField
django how to display users full name in FilteredSelectMultiple
Django ModelChoiceField drop down box custom population
customize select in django admin
Use method other than unicode in ModelChoiceField Django
Django uses unicode(obj) (or the related function, str(obj)) in a number of places. Most notably, to display an object in the Django admin site and as the value inserted into a template when it displays an object.
Please see __unicode__ from https://docs.djangoproject.com/en/dev/ref/models/instances/
You can change __unicode__ method of User class. See below example codes.
from django.db import models
from django.contrib.auth.models import User
def myunicode(self):
return self.get_full_name()
# Create your models here.
class Item(models.Model):
User.__unicode__ = myunicode
user = models.ForeignKey(User)
name = models.CharField("name", max_length=60)
def __unicode__(self):
return self.name

Django - Dynamically importing a models form

I want to create a view that is able to show a ModelForm for various different models. It does this by obtaining the content type of the model and then dynamically instantiating the model form associated with that particular model. Here is my model:
from django.db import models
class SomeModel(models.Model):
name = models.CharField(max_length=150)
def __unicode__(self):
return self.name
And inside the same app there is a forms.py with the following form:
from django.forms import ModelForm
from someapp.models import SomeModel
class SomeModelForm(ModelForm):
class Meta:
model = SomeModel
fields = ('name',)
So what I want to do inside of my view file is return the correct form for each model dynamically. I tried the following:
from django.db import models
from someapp.forms import SomeModelForm
class SomeModel(models.Model):
name = models.CharField(max_length=150)
form = SomeModelForm
def __unicode__(self):
return self.name
But it doesn't work because of the obvious circular import. Does anyone have any idea how I might go about achieving this? I tried toying with modelform_factory, but it seems to ignore any of my custom model forms in forms.py.
EDIT: I should of mentioned that I won't have an instance of the model, just the model class itself, so having a method that inside of the model doesn't work (it does, however, work if you are calling it on an instance of the model)
You could get around the circular import by importing your model form inside a method.
class SomeModel(models.Model):
name = models.CharField(max_length=150)
#staticmethod
def get_form_class():
from someapp.forms import SomeModelForm
return SomeModelForm
# in your view:
SomeModel.get_form_class()
Putting the import within a method on the model should be enough to get you around the circular import, so instead of what you have, you'd use:
class SomeModel(models.Model):
...
def get_form(self):
from someapp.forms import SomeModelForm
return SomeModelForm
You can even make it a property if you want with:
form = property(get_form)
There is a built-in func get_model for lazy importing models.
from django.db.models import get_model
SomeModel = get_model('your_app_name', 'SomeModel')
Using __import__ and getattr.
# models.py
class SomeModel(models.Model):
...
#classmethod
def get_form(cls):
try:
app = __import__(cls._meta.app_label)
forms = getattr(app, "forms")
return getattr(forms, "%sForm" % cls.__name__)
except:
return None
# forms.py
class SomeModelForm(forms.Form):
...
in a view you can get the form associate to a models like this:
# views.p
from models import SomeModel
...
def myview(request):
form = SomeModel.getform()