How to get fields of foreign key - python

In models.py:
class Comment(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
body = models.TextField()
rating = models.FloatField(null=True)
aggregate = models.FloatField(null=True)
date = models.DateTimeField(auto_now_add=True)
class Item(models.Model):
id_item = models.AutoField(primary_key='true')
item_name = models.CharField(max_length=100, null=False)
slug = models.SlugField(max_length=250, blank=True, null=True)
item_description = models.TextField()
item_img = models.ImageField(blank=True, null=True, upload_to="static/item/cover/")
tags = TaggableManager()
In views.py:
def detail(request, slug_text):
details = Item.objects.filter(slug=slug_text)
if details.exists():
reviews = Comment.objects.filter(item=slug_text)
details = details.first()
average = reviews.aggregate(Avg("rating"))["rating_avg"]
average = round(average, 2)
form = CommentForm()
if request.method == "POST":
form = CommentForm(request.POST, author=request.user, item=details)
if form.is_valid():
form.save()
return HttpResponseRedirect(slug_text)
else:
return HttpResponse('<h1>Trang không tồn tại</h1>')
return render(request, 'homepage/detail.html', {'detail': details, 'form': form, 'average': average})
What if I want to get the item.slug = slug_text field in here?
reviews = Comment.objects.filter(item=slug_text)

You not far from it, to get data from a foreignkey you use double under score __ i.e: to get item slug use item__slug see below
reviews = Comment.objects.filter(item__slug=slug_text)
All the best.

Related

Django model with multi foreign key takes too long to load with forms.ModelChoiceField

I have a django project for student marks.
Models.py
class Registration(CMTracking):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
academic_year = models.ForeignKey(AcademicYear, on_delete=models.CASCADE)
school = models.ForeignKey(School, on_delete=models.CASCADE)
grade = models.CharField(max_length=5, choices=Grade.choices)
school_class = models.ForeignKey(SchoolGradeClass, on_delete=models.CASCADE, blank=True, null=True)
last_year_result = models.PositiveSmallIntegerField(choices=RESULT.choices, blank=True, null=True)
last_grade = models.CharField(max_length=5, choices=Grade.choices, null=True)
date_of_join = models.DateField(null=True, blank=True)
type_of_registration = models.PositiveSmallIntegerField(choices=TypeOfRegistration.choices, default=0, null=True)
type_of_attendance = models.PositiveSmallIntegerField(choices=TypeOfAttendance.choices, null=True)
transfer_from = models.PositiveSmallIntegerField(choices=TransferFrom.choices, blank=True, default=1)
status = models.PositiveSmallIntegerField(choices=RequestStatus.choices, default=0)
class Exam(CMTracking):
fa_name = models.CharField(max_length=70, null=False)
en_name = models.CharField(max_length=70, null=False)
ar_name = models.CharField(max_length=70, null=False)
total_mark = models.DecimalField(max_digits=5, decimal_places=2, default=0)
exam_type = models.PositiveSmallIntegerField(choices=ExamType.choices)
academic_year = models.ForeignKey(AcademicYear, on_delete=models.CASCADE)
class ExamSubject(CMTracking):
exam = models.ForeignKey(to=Exam, on_delete=models.CASCADE)
subject = models.ForeignKey(to=SubjectMaster, on_delete=models.CASCADE)
teacher = models.ForeignKey(Staff, related_name='ExamSubjectList', on_delete=models.CASCADE) # Namavar
school_class = models.ForeignKey(SchoolGradeClass, on_delete=models.CASCADE, blank=True, null=True)
min = models.PositiveSmallIntegerField(null=True)
max = models.PositiveSmallIntegerField(null=True)
class MarkDescriptive(CMTracking):
subject = models.ForeignKey(ExamSubject, on_delete=models.CASCADE)
student = models.ForeignKey(Registration, related_name='mark_list_descriptive', on_delete=models.CASCADE)
goal = models.ForeignKey(to=SubjectGoalsMaster, on_delete=models.CASCADE)
point = models.FloatField(null=True, blank=True)
t2point = models.FloatField(null=True, blank=True)
forms.py:
class MarkDescriptiveModelForm2(forms.ModelForm):
student = forms.ModelChoiceField(queryset=Registration.objects.all().select_related('student__person').filter(school_id=106), required=False)
# student = forms.IntegerField() # only shows the id
goal = forms.ModelChoiceField(queryset=SubjectGoalsMaster.objects.all(), required=False)
point = forms.ChoiceField(choices=DescriptivePoint5.choices)
t2point = forms.ChoiceField(choices=DescriptivePoint5.choices)
class Meta:
model = MarkDescriptive
fields = ['id', 'student', 'point', 't2point']
Views.py:
#login_required()
#require_http_methods(['POST', 'GET', 'PUT'])
def mark_descriptive_update(request, exam_subject_id=None, goal_id=None):
subject = get_object_or_404(ExamSubject, id=exam_subject_id)
goal = get_object_or_404(SubjectGoalsMaster, id=goal_id)
MarkFormset = modelformset_factory(MarkDescriptive, form=MarkDescriptiveModelForm2, extra=0)
marks = subject.markdescriptive_set.all().select_related('subject__exam') \
.select_related('student__academic_year') \
.select_related('student__student__person') \
.select_related('goal').select_related('subject__subject').filter(goal=goal)
formset = MarkFormset(request.POST or None, queryset=marks)
add_url = reverse('add-class')
template = 'school/loaders/load_form.html'
form_template = 'school/pages/exam/mark_descriptive/formset.html'
context = {
# 'form': form,
'records': marks,
'subject': subject,
'goal': goal,
'formset': formset,
'template': template, 'form_template': form_template, 'add_url': add_url}
# if request.method == 'PUT':
if request.method == 'POST':
print(f'\n\n\nrequest is {request.method}\n')
print(f'formset data:{formset.data}')
if formset.is_valid():
print('formset is valid')
for form in formset:
updated_mark = form.save(commit=False)
updated_mark.subject = subject
updated_mark.goal = goal
updated_mark.modified_by = request.user
updated_mark.last_modified = datetime.now()
updated_mark.save()
print('*** \n Marks added succefully !\n***')
else:
print(' form not valid', formset.errors)
return render(request, form_template, context)
issue ::
student = forms.ModelChoiceField(queryset=Registration.objects.all().select_related('student__person').filter(school_id=106), required=False)
Takes too long to load student details I tried to override the form to get only students that are in the same exam but couldn't do that. and overall I do not need at all the student field to be as selection. a normal label of student name is totally enough as the data already populated and teacher will only enter the point.

Django Form with dependent ForeignKey forms on one Page

Good day, I am trying to implement django with a dependent foreignkey forms on one page. I have three moodels Store, Product, and ProductClothing. They are all ForeignKey related respectively. Users get to create their store seperately, and are redirected to the store detail view where they will now have to upload Products. But this time, I want them to upload both products and product clothing at once. Below is my models.py and views.py of what I have currently on the store detail view. Also the error I get is:
error.py
NOT NULL constraint failed: product_productclothing.product_id
models.py
class Store(models.Model):
owner = models.ForeignKey(Profile, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=100, unique=True)
slug = AutoSlugField(populate_from='name', unique=True)
description = models.CharField(max_length=255, blank=True)
def __str__(self):
return self.name
class Product(models.Model):
store = models.ForeignKey(Store, null=True, on_delete=models.SET_NULL)
owner = models.ForeignKey(Profile, null=True, on_delete=models.SET_NULL)
title = models.CharField(max_length=255)
price = models.DecimalField(max_digits=9, decimal_places=2, verbose_name=_("Regular price"))
class ProductClothing(models.Model):
CLOTHING_GENDER_CHOICES = (
('M', 'Male',),
('F', 'Female',),
('U', 'Unisex',),
)
CLOTHING_TYPE_CHOICES = (
('dress', 'Dresses',),
('fabric', 'Fabrics',),
('shirt', 'Shirts',),
('suit', 'Suits',),
('tshirt', 'T-Shirts',),
('base_layers', 'Base_Layers',),
('blazer', 'Blazers',),
)
product = models.OneToOneField(Product, on_delete=models.CASCADE)
gender = models.CharField(max_length=10, choices=CLOTHING_GENDER_CHOICES, blank=True, null=True)
clothing_type = models.CharField(max_length=255, choices=CLOTHING_TYPE_CHOICES, blank=True, null=True)
def __str__(self):
return self.product.title
views.py
#login_required
def store_dashboard_view(request, slug):
store = get_object_or_404(Store, slug=slug)
new_product = None
product_clothing = None
if request.user.profile == store.owner:
if request.method == 'GET':
product_form = ProductForm()
product_clothing_form = ProductClothingForm()
if request.method == 'POST':
product_form = ProductForm(data=request.POST)
product_clothing_form = ProductClothingForm(data=request.POST)
if product_form.is_valid() and product_clothing_form.is_valid():
new_product = product_form.save(commit=False)
product_clothing_form.save(commit=False)
new_product.store = store
new_product.owner = request.user.profile
product = product_form.save()
product = product
product_clothing_form.product = product
product_clothing_form.save()
print(request.user.first_name)
return redirect('/')
context = {
"object":store,
"form": product_form,
"product_clothing_form": product_clothing_form
}
return render(request, "store/store-dashboard.html", context)
else:
return redirect('store:store-detail-view', slug=store.slug)
Try to Change this part
if product_form.is_valid() and product_clothing_form.is_valid():
new_product = product_form.save(commit=False)
product_clothing_form.save(commit=False)
new_product.store = store
new_product.owner = request.user.profile
product = product_form.save()
product = product
product_clothing_form.product = product
product_clothing_form.save()
print(request.user.first_name)
return redirect('/')
to
if product_form.is_valid() and product_clothing_form.is_valid():
new_product = product_form.save(commit=False)
product_clothing_form = product_clothing_form.save(commit=False)
new_product.store = store
new_product.owner = request.user.profile
new_product.save() #this is correct your mistake was here
print(new_product)
product_clothing_form.product = new_product
product_clothing_form.save()
print(request.user.first_name)
return redirect('/')

Getting error during adding a comment as notnull

I don't understand why I am getting this one I tried making null=True, blank=True but still, it does not solve my error, at last, I thought of sending it here ...!! please tell me where I am going wrong
Models.py
class Certification(models.Model):
id = models.UUIDField(default=uuid.uuid4,
unique=True, primary_key=True, editable=False)
course_name = models.CharField(max_length=255)
course_image = models.ImageField()
course_taken = models.CharField(max_length=255)
mentor_name = models.CharField(max_length=20, blank=True, null=True)
slug = models.SlugField(unique=True, null=True)
#body = RichTextField()
body = RichTextUploadingField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.course_name
class Comment(models.Model):
certificate = models.ForeignKey(Certification, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
body = models.TextField(null=True, blank=True)
forms.py
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = '__all__'
exclude = ['certificate']
def __init__(self, *args, **kwargs):
super(CommentForm, self).__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update(
{'class': 'form-control form-control-sm',})
self.fields['body'].widget.attrs.update(
{'class': 'form-control form-control-sm',})
Views.py
def certificatePage(request,pk):
certi = Certification.objects.get(id=pk)
count = certi.comment_set.count()
comments = certi.comment_set.all()
form = CommentForm()
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.certi = certi
comment.save()
context = {
"certi": certi,
'count':count,
'comments':comments,
'form':form
}
return render (request, 'base/certificate.html',context)
Click On The Image To See The Error

Select particular instance of a model with Foreign Key to another model

I have these models
class Review(models.Model):
# SET_NULL ensures that when a company is deleted, their reviews remains
company = models.ForeignKey(Company, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
# SET_NULL ensures that when a user is deleted, their reviews get deleted too
review_text = models.TextField(max_length=500, verbose_name='Your Review: (Maximum of 200 Words)')
rating = Int_max.IntegerRangeField(min_value=1, max_value=5)
date_added = models.DateField('Review Date', auto_now_add=True)
def __str__(self):
return self.review_text
class Response(models.Model):
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
review = models.ForeignKey(Review, on_delete=models.CASCADE)
response = models.TextField(max_length=200, verbose_name='Your Response')
date_added = models.DateField('Response Date', auto_now_add=True)
def __str__(self):
return self.response
class ResponseReply(models.Model):
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
response = models.ForeignKey(Response, on_delete=models.CASCADE)
review = models.ForeignKey(Review, on_delete=models.CASCADE)
reply = models.TextField(max_length=200, verbose_name="Your Reply")
date_added = models.DateField('Response Date', auto_now_add=True)
def __str__(self):
return self.reply
How to I select ResponseReply belonging to a particular response which also has a foreign key to a particular review.
My view rather returns a list instead of an object of the Review Model since there are more than one review. Below is my view:
def profile_company(request):
print(request.user)
company = get_object_or_404(Company, user=request.user)
review = get_object_or_404(Review, company=company)
responses = get_list_or_404(Response, review=review)
response = get_object_or_404(Response, review=review)
responses = get_list_or_404(Response, review=review)
reply = get_object_or_404(Response, response=response)
company_reviews = company.review_set.all()
total_reviews = len(company_reviews)
print(company.average_rating)
form = ResponseForm()
if request.method == "POST":
form = ResponseForm(request.POST or None)
if form.is_valid:
data = form.save(commit=False)
data.user = request.user
data.review = review
data.save()
return redirect('profile_company')
context = {
'company': company,
'company_reviews': company_reviews,
'total_reviews': total_reviews,
'form': form,
'responses': responses,
'reply': reply,
}
return render(request, 'companyusers/profile_company.html', context)
The problem is when I call response = get_object_or_404(Response, review=review) it fails since the review can be more than one. How do I select a particular response belonging to a particular review. To enable me select associated replies.
Thank you so much!

Editing form and saving into database

I have a form that takes information about an item and saves it into the database. Im trying to allow users to edit that form with new/different information and save it again. Im having some difficulty trying to get this to work. I think the problem is when Django validates the data it sees that the slug and unique id of the item already exist and doesnt allow it to validate the data but im not completely sure about this as well. Would really appreciate the help. Thanks.
#view
def edit_item(request, item_id):
if request.method == 'POST':
item = Item.objects.get(id=item_id)
form = AddItem(request.POST,instance=item)
if form.is_valid():
item = form.save(commit=False)
item.user = request.user
item.is_active = True
item.slug = slugify(item.name)
item.save()
return HttpResponseRedirect('thanks.html')
else:
form = AddItem(instance=item )
return render_to_response('forsale.html', locals(), context_instance=RequestContext(request))
#form
class AddItem(forms.ModelForm):
name = forms.CharField(label="Title")
class Meta:
model = Item
exclude = ('user','slug','is_active',)
#model
class Item(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=30)
slug = models.SlugField(max_length=50, unique=True)
is_active = models.BooleanField(default=True, blank=True)
image1 = models.ImageField(upload_to='img')
image2 = models.ImageField(upload_to='img', blank=True)
image3 = models.ImageField(upload_to='img', blank=True)
image_caption1 = models.CharField(max_length=200, blank=True)
image_caption2 = models.CharField(max_length=200, blank=True)
image_caption3 = models.CharField(max_length=200, blank=True)
price = models.DecimalField(max_digits=8, decimal_places=2)
quantity = models.IntegerField(default=1)
description = models.TextField()
created = models.DateTimeField(auto_now_add=True)
shipping_price = models.DecimalField(decimal_places=2, max_digits=6)
categories = models.ManyToManyField(Category)
def save(self, *args, **kwargs):
super(Item, self).save(*args, **kwargs)
if not self.slug:
self.slug = slugify(self.product.title) + "-" + str(self.id)
self.save()
Update your view function like this to return form for get request as well:
def edit_item(request, item_id):
if request.method == 'POST':
item = Item.objects.get(id=item_id)
....
#your existing code
else: #if its GET request
item = Item.objects.get(id=item_id)
form = AddItem(instance=item )
return render_to_response('forsale.html', locals(),
context_instance=RequestContext(request))
Note: you need to handle case when item with item_id does not exists in the DB. In that case do not use instance parameter to instantiate the form.

Categories