models.py:
from django.db import models
class Course(models.Model):
course = models.TextField(blank=True)
class Student(models.Model):
first_name = models.TextField()
last_name = models.TextField()
course = models.ManyToManyField(Course)
forms.py:
from django import forms
from .models import Student, Course
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ['first_name', 'last_name', 'course']
class CourseForm(forms.ModelForm):
class Meta:
model = Course
fields = ['course']
views.py:
def students_view(request):
if request.method == 'POST':
students_form = StudentForm(request.POST)
if students_form.is_valid():
students_form.save()
print(Student.objects.all().values())
students_form = StudentForm()
context = {
'form':students_form
}
return render(request, 'courses/courses.html', context)
If I print print(Student.objects.all().values()) than I see student's ID, first_name and last_name. But I don't see in which groups they belong to. How to print that?
Like this for example:
students = Student.objects.prefetch_related("course")
print([(s, list(s.course.all()),) for s in students])
Related
In my project, the relationship between Product and Group is ManytoOne.
When I tried to post a new product, it cannot work.
I'm sure there are more issues with this code and I will appreciate a detailed answer, because I am new to Django and Python. Thank you in advance.
models.py
class Group(models.Model):
productType = models.CharField(max_length=100)
intervalTime = models.IntegerField()
created = models.DateTimeField(auto_now_add=True)
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True,editable=False)
def __str__(self):
return self.productType
class Product(models.Model):
productName = models.CharField(max_length=255)
color = models.CharField(max_length=255)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True,editable=False)
def __str__(self):
return self.productName
serializers.py
class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = Group
fields = ('id','productType','intervalTime')
class ProductSerializer(serializers.ModelSerializer):
group = GroupSerializer(many=False)
class Meta:
model = Product
fields = ('id','productName','color','group')
def create(self, validated_data):
group = validated_data.pop('group')
product = Product.objects.create(**validated_data)
for group_instance in group:
Group.objects.create(**group_instance, product=product)
return product
views.py
#api_view(['POST'])
def createProduct(request):
serializer = ProductSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
First change serializers.py:
class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = Group
fields = ('id','productType','intervalTime')
class ProductInfoSerializer(serializers.ModelSerializer):
group = GroupSerializer(read_only=True)
class Meta:
model = Product
fields = ('id','productName','color','group')
class ProductCreationSerializer(serializers.ModelSerializer):
group = serializers.SlugRelatedField(slug_field='productType', queryset=Group.objects.all())
class Meta:
model = Product
fields = ('productName','color','group')
Then change views.py:
from rest_framework import status
#api_view(['POST'])
def createProduct(request):
serializer = ProductCreationSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
instance = serializer.save()
return Response(status=status.HTTP_200_OK, data=ProductInfoSerializer(instance=instance).data)
I am getting the Value Error: Cannot query "post": Must be "UserProfile" instance when I make a get request to call PostListView.as_view().
Here is my model.py :
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
username = models.CharField(max_length=30)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField()
password = models.CharField(max_length=100)
def __str__(self):
return self.user.username
class Post(models.Model):
user = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
views.py :
class PostListView(ListAPIView):
serializer_class = PostSerializer
permission_classes = [AllowAny]
def get_queryset(self):
"""Returns only the object related to current user"""
user = self.request.user
return Post.objects.filter(user=user)
Also, I want a Foreign key relationship exists between User and Post on Model-level, not on the Database level.
user is UserProfile instance but request.user is a User instance
change this line like that to refernece to userprofile
user = self.request.user.userprofile
I connected my database to django. I want to enable user (teacher) insert the name of a student and get test results on certain subjects.
I run python3 manage.py inspectdb and inserted it into models.py
class Profilez(models.Model):
student = models.CharField(max_length=255)
schgroup = models.CharField(max_length=255)
class Meta:
managed = False
db_table = 'profilez'
class Schoolz(models.Model):
profilez_id = models.AutoField(primary_key=True)
lit = models.IntegerField(blank=True, null=True)
math = models.IntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = 'schoolz'
in forms.py i put:
class StudentForm(forms.ModelForm):
SUB = (
('lit', 'lit'),
('math', 'math')
)
student = forms.CharField(max_length=150, label='', widget=forms.TextInput)
class Meta:
model = Schoolz
fields = ('student',)
in views.py:
def home(request):
if request.method == "POST":
form = StudentForm(request.POST)
if form.is_valid():
form1 = form.save(commit=True)
name = form1.student
ab=schoolz.objects.all()
context={
'name':name,
}
return render(request, 'book/analysis.html', context)
else:
form = StudentForm()
return render(request, 'book/search.html', {'form': form})
Can you please help me to understand what i am doing wrong and how to get value for certain subject for exmaple math subject.
I would appreciate help and guidance to undertand and execute it. I am struggling a month.
Notes
Add a field in Profile that should be unique for each student. Currently I am assuming name and surname combination will be unique.
If you use ajax, you can get score without refresh. Current way I have used is not very good.
You don't have to write models if you already have in DB. You can remove your models. add already present models in models.py and makemigrations and migrate.
Add a ForiegnKey field in Class10
class Class10(models.Model):
profile_id = models.IntegerField()
math = models.IntegerField()
literature = models.IntegerField()
biology = models.IntegerField()
student = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='stud_name') # add this in model
class Meta:
managed = False # make this True otherwise makemigrations won't get the changes.
db_table = 'class_10'
class Profile(models.Model):
student_name = models.CharField(max_length=255)
student_surname = models.CharField(max_length=255)
class Meta:
managed = False
db_table = 'profile'
views.py
def home(request):
if request.method == "POST":
form = StudentlForm(request.POST)
if form.is_valid():
form_1 = form.save(commit=False)
name = form_1.student_name
surname = form_1.student_surname
subject = form_1.subject
fil = Q(student__student_name=name) & Q(student__student_surname=surname)
student_1 = StudentScore.objects.filter(fil).values()
score = student_1[0][subject] # answer
context={
'score':score
}
return render(request, 'school/analysis.html', context)
else:
form = StudentlForm()
return render(request, 'school/search.html', {'form': form})
forms.py
class StudentForm(forms.ModelForm):
SUB = (
('math', 'math'),
('literature', 'literature'),
('biology', 'biology')
)
student_name = forms.CharField(max_length=150, label='', widget=forms.TextInput)
student_surname = forms.CharField(max_length=150, label='', widget=forms.TextInput)
subject = forms.CharField(widget=forms.Select(choices=SUB))
class Meta:
model = Profile
fields = ('student_name', 'student_surname', 'subject')
#Nina,
Please look on the relationship> it's general idea for the Student & Gradesheet model
class Student(models.Model):
std_name = models.CharField(max_length=100)
def __str__(self):
return self.std_name
class Gradesheet(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
sub = models.CharField(max_length=50)
grade = models.CharField(max_length=50)
def __str__(self):
return self.student.std_name
So if you need to search for a student grade for particular subject:
std_info = Student.objects.get(std_name='Nina')
Then you will get a Student Class instance for Nina.
Now fetch the data by relationship:
std_grade = std_info.gradesheet_set.filter(sub='math')
You will get QuerySet. Then just :
std_grade[0].grade
You will get your student's grade for particular subject. Look its a model relationship. So you may use other filtering options also to get your desired result.
According to your given model:
Instead of the profile_id you should use the Profile object which will help you to take the control through django ORM.
class Profile(models.Model):
student_name = models.CharField(max_length=255)
student_surname = models.CharField(max_length=255)
class Meta:
managed = False
db_table = 'profile'
class Class10(models.Model):
#profile_id = models.IntegerField()
profile = models.OneToOneField(Profile, on_delete=models.CASCADE,related_name='profile')
math = models.IntegerField()
literature = models.IntegerField()
biology = models.IntegerField()
class Meta:
managed = False
db_table = 'class_10'
So your query can be build by:
std_profile = Profile.objects.get(student_name='SomeoneName')
Now turn it for get the grade. Result would be:
math_grade = std_profile.profile.math
biology_grade = std_profile.profile.biology
literature_grade = std_profile.profile.literature
average_grade = ((math_grade + biology_grade + literature_grade)/3)
Here, your model relationship:Profile to Class10 is OneToOne
I have code where Product model has M2M field Comment model. I made methods in views.py for getting Product by id and all objects of Product, but there's problem with updating it. I can't fully understand how to update Product comments field. I already tried a lot of different answers and ideas, but nothing helps me. I'm using PUT method for update.
My main questions:
Where and how target Product id in order to update comments field in it?
After I find Product by it's id how I can update M2M field comments in it?
I tried:
Completely Lost: Many To Many with Serializers and Update in Django Rest Framework
Doesn't work at all, screams for 'collections.OrderedDict' object has no attribute 'id'
Django Rest update many to many by id
It's making PrimaryKeyRelatedField which is not correct for me.
How to update many to many Django REST?
Not enough information in answer, got stuck on it.
I read, but found no usefull information on my problem
products/models.py
from django.db import models
from comments.models import Comment
# Create your models here.
class Product(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=150, blank=True)
description = models.TextField(default="No description")
category = models.CharField(max_length=255, blank=True)
price = models.DecimalField(default=100, max_digits=15, decimal_places=2, blank=True)
photo_one = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True, null=True)
photo_two = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True, null=True)
photo_three = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True, null=True)
photo_four = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True, null=True)
is_popular = models.BooleanField(default=False)
is_hit = models.BooleanField(default=False)
has_sale = models.IntegerField(default=0)
comments = models.ManyToManyField(Comment, blank=True)
def __str__(self):
return self.name
comments/models.py
import uuid
from django.db import models
# Create your models here.
class Comment(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
username = models.CharField(max_length=255, default="default")
text = models.TextField()
rating = models.IntegerField()
def __string__(self):
return self.username
products/serializers.py
class ProductSerializer(serializers.ModelSerializer):
comments = CommentSerializer(many=True)
class Meta:
model = Product
fields = '__all__'
def update(self, instance, validated_data):
submitted_comments = validated_data.get('comments')
if submitted_comments:
for comment in submitted_comments:
comment_instance = Comment.objects.get(id=comment.id)
instance.children.add(comment_instance)
instance.save()
return instance
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ('id', 'username', 'text', 'rating')
products/views.py
import django_filters
from rest_framework import status
from rest_framework.generics import ListAPIView, RetrieveUpdateAPIView
from rest_framework.response import Response
from .models import Product
from .pagination import CustomPagination
from .serializers import ProductSerializer
class GetProductById(RetrieveUpdateAPIView):
serializer_class = ProductSerializer
filter_class = ProductFilter
queryset = Product.objects.all()
def get_product(self, pk):
try:
product = Product.objects.get(pk=pk)
except Product.DoesNotExist:
content = {
'status': 'Not Found'
}
return Response(content, status=status.HTTP_404_NOT_FOUND)
return product
def get(self, request, pk):
product = self.get_product(pk)
serializer = ProductSerializer(product)
return Response(serializer.data, status=status.HTTP_200_OK)
class ProductFilter(django_filters.FilterSet):
product_id = django_filters.UUIDFilter(name='id')
class Meta:
model = Product
fields = ['id']
class GetProducts(ListAPIView):
serializer_class = ProductSerializer
pagination_class = CustomPagination
def get_queryset(self):
products = Product.objects.all()
return products
def get(self, request):
products = self.get_queryset()
paginate_queryset = self.paginate_queryset(products)
serializer = self.serializer_class(paginate_queryset, many=True)
return self.get_paginated_response(serializer.data)
*products/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('api/products/', views.GetProducts.as_view(), name='get_products'),
path('api/product/<pk>/', views.GetProductById.as_view(), name='get_put_product')
]
I expect successful target by Product id and finding product.comments field
I expect successful adding new Comment to Product in it's comments field
I've a registration form, where user must chose one of 2 options.
Django renders all correctly, django admin also have it ok, but db records all possible choices as value.
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email','password1','password2']
class UserProfileForm(forms.ModelForm):
terms_compliance = forms.BooleanField(label=mark_safe('I agree with terms and conditions '))
class Meta:
model = UserProfile
widgets = {'role': forms.RadioSelect}
fields = ('role','terms_compliance')
def __init__(self):
self.fields['terms_compliance'].initial = True
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
role_choices = [('publisher','Publisher'), ('advertiser','Advertiser')]
role = models.CharField(max_length=15, choices=role_choices, default=None)
terms_compliance = models.BooleanField()
def __str__(self):
return self.user.username
In new instance (which is user.userprofile.role_choices) I need advertiser or publisher, but all I have is: [('publisher','Publisher'), ('advertiser','Advertiser')]
If you want to provide choices in a Database Field. Do like this:
class UserProfile(models.Model):
class RoleChoice(ChoiceEnum):
PUBLISHER = 'Издатель'
ADVERTISER = 'Рекламодатель'
user = models.OneToOneField(User, on_delete=models.CASCADE)
role = models.CharField(max_length=15, choices=RoleChoice.choices(), default=None)
terms_compliance = models.BooleanField()
def __str__(self):
return self.user
In Views.py, populate the DB like this.
For example:
...
choice = request.query_params.get('choice') or UserProfile.RoleChoice.PUBLISHER.value
...
For more details read from here: https://django-mysql.readthedocs.io/en/latest/model_fields/enum_field.html