Pass array of objects to another model call django - python

I am trying to select all class for a user and then load all of the classes objects that are corresponding. Here is my model.py file:
from django.db import models
from django.contrib.auth.models import User
class Class(models.Model):
name = models.CharField(max_length=150)
description = models.TextField()
teacher = models.ForeignKey(User)
class UserClasses(models.Model):
class_name = models.ForeignKey(Class)
user = models.ForeignKey(User)
And here is the call i'm making:
def index(request):
#grab all classes for a user
users_classes = UserClasses.objects.filter(user=request.user)
#pass the array of class objects and get their info
classes = Class.objects.select_related(self=users_classes)
context_dict = {}
return render(request, 'dashboard/index.html', context_dict)
How can I achieve the above?

You can do
users_classes = UserClasses.objects.filter(user=request.user)
classes = Class.objects.filter(class_name__in=users_classes)
Now classes objects contains all class which user belongs to.

Related

Calculate a field django and save it in the database

I am just starting with Django and web development , so please be nice with me. i am trying to build an app that generates a new number to reports created by our inspectors (our company is an inspection company). each inspector chooses the type of reports, the inspection date and the client and the app saves the data and creates a report number . the report number is generated depending on the type of the report and the date. for example if i have 3 reports of type "visual inspection" done in 2022, the new "visual inspection" report will have the number 4/2022.
here is the code I used to attempt this but unfortunately it is not working:
Views.py
from modulefinder import ReplacePackage
from django.shortcuts import render
from report.models import Report
from django.http import HttpResponse
from django.db.models.aggregates import Count
from django.db import transaction
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import ReportSerializer
#api_view(['GET','POST'])
def Report_add_view(request):
if request.method =='GET':
queryset = Report.objects.select_related('type').all()
serializer = ReportSerializer(queryset,many=True)
return Response(serializer.data,status=status.HTTP_200_OK)
elif request.method =='POST':
serializer = ReportSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data,status=status.HTTP_201_CREATED)
# Create your views here.
models.py
from django.db import models
# Create your models here.
class Client(models.Model):
name = models.CharField(max_length = 255)
code = models.PositiveIntegerField()
class ReportType(models.Model):
report_type = models.CharField(max_length = 255)
report_code = models.CharField(max_length = 255)
report_rev = models.CharField(max_length = 20)
def __str__(self):
return self.report_type
class Inspector(models.Model):
first_name = models.CharField(max_length = 255)
last_name = models.CharField(max_length = 255)
full_name = models.CharField(max_length = 255)
class Report (models.Model):
number = models.CharField(max_length=100)
type = models.CharField(max_length = 255)
inspection_date = models.DateField()
date_created = models.DateTimeField(auto_now_add=True)
inspector = models.ForeignKey(Inspector,on_delete=models.PROTECT)
client = models.ForeignKey(Client,on_delete=models.PROTECT)
type = models.ForeignKey(ReportType,on_delete=models.PROTECT)
reportlink = models.TextField()
serializers.py
from rest_framework import serializers
from .models import *
from django.db.models.aggregates import Count
from django.db.models import F
class ReportSerializer(serializers.ModelSerializer):
class Meta:
fields = ['number','type','inspection_date','inspector','client','reportlink','date_created']
model = Report
number = serializers.SerializerMethodField(method_name='report_number')
def report_number(self, report:Report):
print(report.type_id)
num1 = Report.objects.filter(type_id = report.type_id).all().aggregate(num=Count('id'))['num']+1
year = str(report.inspection_date)[:4]
print(year)
print(num1)
return str(num1) + "/"+ year
class InspectorSerializer(serializers.ModelSerializer):
class Meta:
fields = ['first_name','last_name','full_name']
model = Inspector
class ReportTypeSerializer(serializers.ModelSerializer):
class Meta:
fields = ['report_type','report_code','report_rev']
model = Report
screenshot of api result:
database screenshot:
As stated in the DRF doc: https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
SerializerMethodField is a read_only field.
To achieve what you're trying to do, i would override the "create" method of the serializer. It takes a dict of validated_data as parameter (generate thanks to the is_valid call you're doing).
In this method, you should be able to set validated_data["number"] with your desired value (return the modified dict at the end of the "create" method).
I'm not sure, but i think you should remove "number" from your list of fields in the serializer since you're calculating it.

There is a way to get a value from views.py into nodels.py?(Django)

I'm making a little Django project of money management, I'm using a table layout, inside the tables there are many transactions. I have two SQL tables: "Table" and "Transactions" and I need that when I open the link of one specific table, I need to get just the items which were created in the table page.
Example:
I open 'table1' and inside it I create 'value1', 'value2','value4'
after, I open 'table2' and inside it I create 'value3' and 'value5'
after that, when I open the 'table1' page I need to show
'value1','value2' and 'value4'
and when I open 'table2', I need 'value3' and 'value5'
I wonder if there is a way to take the id of the table I'm inside in the moment and write it into the transactions form to make some kind of 'id', so I can filter the values by it id
Here are my files:
urls.py
from django.urls import path
import tables1.views as vw
urlpatterns = [
path('admin/', admin.site.urls, name = 'admin'),
path('mytables/', vw.mytables, name = 'mytables'),
path('',vw.home),
path('table/<int:pk>',vw.table, name = 'tableurl'),
path('newtable/',vw.newtable,name = 'newtable')
]
views.py
from .models import Table
from .forms import TableForm
def home(request):
now = {}
return render(request,'tables1/home.html',now)
def mytables(request):
data = {}
data['tables'] = Table.objects.all()
return render(request, 'tables1/mytables.html', data)
def table(request,pk):
form = TableForm(request.POST or None)
data = Table.objects.get(idd = pk)
print(data)
if form.is_valid():
form.save()
return redirect('mytables')
return render(request,'tables1/table.html',{'data':data, 'form':form}),pk
def newtable(request):
form = TableForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('mytables')
return render(request,'tables1/newtable.html',{'form':form})
models.py
from .views import table
class Table(models.Model):
idd = models.AutoField(primary_key=True, default= None)
name = models.CharField(max_length=100)
date = models.DateField(auto_now_add=True)
time = models.TimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Tables'
def __str__(self):
return self.name
class Transacao(models.Model):
mod = models
date = models.DateTimeField()
desc = models.CharField(max_length=200)
value = models.DecimalField(max_digits=7,decimal_places=2)
obs = models.TextField(null=True,blank=True)
class Meta:
verbose_name_plural = 'Transacoes'
def __str__(self):
return self.desc
forms.py
from .models import Table
from .models import Transacao
class TableForm(ModelForm):
class Meta:
model = Table
fields = ['name']
class TransacaoForm(ModelForm):
class Meta:
model = Transacao
fields = ['desc','date','value','obs'] ```
From my understanding of your question, you want a relation between Table and Transaction, where each Table contains (possibly 0 or more) transactions. This is a many-to-one relation that can be done by a Foreign Key. Read more.
I modified your code and added the foreign key to it. By adding the foreign key field name to the form you can set the table for each transaction when you create it. And when you need to get the transactions for a table you can do table.transacoes. The name transacoes is defined in the related-name attribute of the foreign key.
models.py
from .views import table
class Table(models.Model):
idd = models.AutoField(primary_key=True, default= None)
name = models.CharField(max_length=100)
date = models.DateField(auto_now_add=True)
time = models.TimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Tables'
def __str__(self):
return self.name
class Transacao(models.Model):
# Forein key defined here
table = models.FogeinKey(Table, related_name='transacoes')
# Also I don't know what this is, you probably don't need it
mod = models
date = models.DateTimeField()
desc = models.CharField(max_length=200)
value = models.DecimalField(max_digits=7,decimal_places=2)
obs = models.TextField(null=True,blank=True)
class Meta:
verbose_name_plural = 'Transacoes'
def __str__(self):
return self.desc
forms.py
from .models import Table
from .models import Transacao
class TableForm(ModelForm):
class Meta:
model = Table
fields = ['name']
class TransacaoForm(ModelForm):
class Meta:
model = Transacao
# table added here
fields = ['desc', 'date', 'value', 'obs', 'table']
I managed to solve my problem by instead of saving the form data automatically in database with "form.save()", i """manually""" got the data from form using form.cleaned_data for each one of the form fields and saved that data into database using Transaction.objects.create() so that i could save the pk variable into the transactions table with the name of "tableid", that way, the app could link the primary key of each table page and link it to the transactions registered inside that page.

Django filter by multipleChoiceField

I have model Skill
class Skill(models.Model):
hero= models.ForeignKey(Hero)
name = models.CharField(max_length=255)
And I have model Hero
class Hero(models.Model):
name = models.CharField(max_length=255)
I use multiple choice field to select skills
OPTIONS = (
("sharingan", "sharingan"),
("rasengan", "rasengan"),
("fireball", "fireball"),
)
skills= forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(),
choices=OPTIONS)
I use get request to send my form and my search page url becomes something like:
mysite.com/search?skills=shiringan&skills=rasengan
In my views.py I have
def vip(request):
heroes = Hero.objects.all
return render(request, 'app_name/search.html',{'heroes': heroes})
What should I write in views.py to select all heroes with chosen skills?
You probably want to use ManyToManyField Instead.
like this:
# models.py
from django.db import models
class Skill(models.Model):
name = models.CharField(max_length=255)
class Hero(models.Model):
name = models.CharField(max_length=255)
skills = models.ManyToManyField(Skill)
and use forms like this:
# forms.py
from django import forms
from .models import Hero
class HeroForm(forms.ModelForm):
class Meta:
model = Hero
fields = '__all__'
and finally your views:
# views.py
from .models import Hero, Skill
from .forms import HeroForm
def my_heroes(request):
heroes = Hero.objects.all()
return render(request, 'your_template.html', {'heroes':heroes})
def hero_skill_select(request):
if request.method == 'POST':
form = HeroForm(request.POST)
# do something
else:
form = HeroForm()
return render(request, 'template_with_form.html', {'form':form})
Shouldn't the Hero model have Skill as foreignfield, rather than the opposite? I don't understand the logic behind your classes.
Based on your current Classes and their relationship, you could do something like this:
chosen_skills = Skill.objects.values('hero').distinct().annotate(skill='name', hero_name='hero__name')
Haven't tested it, but basically, for every distinct hero, it returns the skill and the name. Let me know if this helps.

Populate Django ManyToManyField Options Based on Other Field in Admin

I am having problems filtering options for a ManyToManyField on the Django Admin Add screen based on input to another field on the same form. I am new to Django and have been unable to use any of the generic fixes described elsewhere because they are all slightly different than my situation. Here is my situation:
I have three models in my project: Class, Student, and AttendanceRecord. In the Django Admin, when adding an attendance record, I would like to change the options for the field Absent_Students based on the selection made for the field Associated_Class. So, for example, if Associated_Class "CS 450" is selected, the options for Absent_Students should change to only students whose class_list includes CS 450.
Here are my models:
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
from django.utils.encoding import python_2_unicode_compatible
import random, string
# Create your models here.
#This is the model for a student
#python_2_unicode_compatible
class Student(models.Model):
pass
Student_First_Name = models.CharField(max_length=200)
Student_Last_Name = models.CharField(max_length=200)
Student_ID_Number = models.CharField(max_length=200)
Student_Class = models.ForeignKey('Class', null=True)
def __str__(self):
return self.Student_Last_Name + ',' + self.Student_First_Name
# This is the model for a class
#python_2_unicode_compatible
class Class(models.Model):
class Meta:
verbose_name_plural = "Classes"
Class_Name = models.CharField(max_length=200)
Student_List = models.ManyToManyField('Student', related_name='class_list')
Professor = models.ForeignKey(User,null=True)
AddCode = models.IntegerField
pass
def __str__(self):
return self.Class_Name
def getName(self):
return self.Class_Name
def getProfessor(self):
return self.Professor.id
def getProf(self):
return self.Professor
def getStudents(self):
return self.Student_List
#This is the model for attendance records
class AttendanceRecord(models.Model):
class Meta:
verbose_name = "Attendance Record"
Associated_Class = models.ForeignKey(Class, on_delete=models.CASCADE, related_name='Attendance_Records')
Date = models.DateField()
Absent_Students = models.ManyToManyField('Student', blank=True)
Present_Students = models.ManyToManyField('Student', related_name='a')
def get_associated_class_id(self):
return self.Associated_Class
def __str__(self):
return self.Associated_Class.__str__() + ' on date ' + self.Date.__str__(self)
I have tried doing this by editing the AttendanceRecordAdminForm class and AttendanceRecordAdmin class. My problem is that when setting the self.fields['Absent_Students].queryset I do not know how to access the currently selected Associated_Class on the form. I keep getting an error that "AttendanceRecord has no Associated_Class". Here are those classes just discussed in their entirety:
class AttendanceRecordAdminForm(forms.ModelForm):
class Meta:
model = AttendanceRecord
fields = '__all__'
def __init__(self, *args, **kwargs):
super(AttendanceRecordAdminForm, self).__init__(*args, **kwargs)
instance = kwargs.get('instance', None)
self.fields['Absent_Students'].queryset = Student.objects.filter(class_list__id=self.instance.get_associated_class_id())
self.fields['Present_Students'].queryset = Student.objects.filter(class_list__id=1)
class AttendanceRecordAdmin(admin.ModelAdmin):
form = AttendanceRecordAdminForm
filter_horizontal = ('Absent_Students', 'Present_Students',)
Basically, I am looking for a way to access the currently entered Associated_Class on the admin form so I can properly filter the queryset.
After hours more of online searching I finally found what I needed. A chained ManyToMany from the smart_select app makes this very easy. This link: How to use django-smart-select describes the install process and also links to the documentation for using it once it is installed. Hopefully this helps some others as well.

Multiple User Profiles in django-userena

I am trying to make multiple profile for Userena - each User can only have one Profile type. Following other discussions, I am using multiple table inhertience, but when I do this, I cannot get data to be saved into the derived models. Everything ends up being CommonProfile, which should not be possible/permitted. Example code follows:
in models.py:
# models.py
# This is an example of how i've attempted to get
# multiple user profiles working with Userena
from django.contrib.auth.models import User
from django.db import models
from userena.models import UserenaLanguageBaseProfile
class CommonProfile(UserenaLanguageBaseProfile):
"""Common fields for 2 user profiles: Spam and Eggs"""
user = models.OneToOneField(User)
common_field = models.CharField(max_length=100)
#property
def is_spam(self):
"""Find out if this is a Spam user"""
try:
self.spamprofile
return True
except SpamProfile.DoesNotExist:
return False
def get_real_type(self):
"""return the real model"""
if self.is_spam:
return self.spamprofile
else:
return self.eggsprofile
class SpamProfile(CommonProfile):
spam_field = models.CharField(max_length=20)
class EggsField(CommonProfile):
eggs_field = models.SmallIntegerField()
in forms.py
# forms.py
# This is the form to sign up a Spam Type Person
from django import forms
from userena.forms import SignupFormTos
from . models import CommonProfile, SpamProfile
class SpamSignupForm(SignupFormTos):
"""signup a Spam Person"""
common_field = forms.CharField(label='what is your quest')
spam_field = forms.CharField(label='what kind of spam are you')
def clean(self):
cleaned_data = super(SpamSignupForm,self).clean()
#do stuf, same idea for clean_<field>
return cleaned_data
def save(self):
"""Save the SpamProfile"""
user = super(SpamSignupForm,self).save()
common_profile = user.get_profile()
spam_profile = SpamProfile(commonprofile_ptr=common_profile)
spam_profile.spam_field = self.cleaned_data['spam_field']
spam_profile.save()
return spam_profile
I had the same problem this weekend. Try in your save function
def save:
#your other code
spam_field = self.cleaned_data['spam_field']
new_spam_user = SpamProfile.objects.create_user(spam_field)
return new_user

Categories

Resources