Connect the username when sending a report in django - python

I am beginner to django and I am trying to create a site to send reports after creating a profile, but when I send the report, the username of the author of the report is not saved, Just (None). I searched a lot about it and did not find it
models.py
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, verbose_name=("user"), null=True, on_delete=models.CASCADE)
identity_No = models.IntegerField( blank=True, null=True)
mobile_No = models.IntegerField( blank=True, null=True)
city = models.CharField( max_length=15,null=True)
class Meta:
verbose_name =("Profile")
verbose_name_plural =("Profile")
def __str__(self):
return '%s' %(self.user)
class Report(models.Model):
user = models.ForeignKey(User, verbose_name=("user"), on_delete=models.CASCADE)
Report_type =models.CharField( max_length=100, blank=True, null=True)
Region =models.CharField( max_length=30, blank=True, null=True)
city =models.CharField( max_length=30, blank=True, null=True)
sector =models.CharField( max_length=30, blank=True, null=True)
report =models.TextField( max_length=3000, blank=True, null=True)
files =models.FileField( blank=True, null=True)
class Meta:
verbose_name =("Report")
verbose_name_plural =("Report")
def __str__(self):
return '%s' %(self.user)
form.py
Shorten the time, attach only the report
class ReportForm(forms.ModelForm):
class Meta:
model = Report
fields = ['Report_type', 'Region', 'city','sector','report','files' ]
view.py
def report(requst):
if requst.method == 'POST':
report_form = ReportForm(requst.POST)
if report_form.is_valid() :
report_form.save()
return redirect ('accounts:home')
else:
report_form = ReportForm()
return render(requst, 'user/report.html', {
'report_form': report_form,
enter image description here })

You can link the new report wrapped in the ReportForm to the logged in user request.user with:
from django.contrib.auth.decorators import login_required
#login_required
def report(requst):
if requst.method == 'POST':
report_form = ReportForm(requst.POST)
if report_form.is_valid():
report_form.instance.user = request.user
report_form.save()
return redirect ('accounts:home')
else:
report_form = ReportForm()
return render(requst, 'user/report.html', { 'report_form': report_form })
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].

Related

How to get username field automatically in Django

I am working on a Django project which is something similar to Fiverr in its working. I have used abstractuser where there is a buyer and seller. The seller creates a gig then the buyer will go through the gig before placing an order. My issue is how to get the seller and place him in the order that the buyer will create from reading the gig. Currently I am using the system whereby the buyer will have to manually choose a gig from a list, which I think is not effective.
Here is my Models.py
`class User(AbstractUser):
is_buyer=models.BooleanField(default=False)
is_seller=models.BooleanField(default=False)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(default='avatar.jpg', null=True, blank=True)
about = models.CharField(max_length=100)
def __str__(self):
return self.user.username
class Gig(models.Model):
seller = models.ForeignKey(Profile, on_delete = models.CASCADE, null=False, blank=False)
category = models.ForeignKey('Category', on_delete = models.CASCADE, null=False, blank=False)
title = models.CharField(max_length=500, null=True, blank=True)
description = models.CharField(max_length=500, null=True, blank=True)
gig_id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True, editable=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Order(models.Model):
buyer = models.ForeignKey(Profile, on_delete=models.CASCADE, null=False, blank=False)
seller = models.ForeignKey(Gig, on_delete=models.CASCADE, related_name='+', null=False, blank=False)
title = models.CharField(max_length=500, null=True, blank=True)
description = models.CharField(max_length=500)
amount = models.IntegerField(max_length=50, blank=False)
is_ordered = models.BooleanField(default=False)
order_id = models.UUIDField(default=uuid.uuid4, unique=True, db_index=True, editable=False)
slug = models.SlugField(null=True)
def __str__(self):
return self.title`
And views.py where I am getting the submissions;
def createOrder(request):
profile = request.user.profile
form = CreateOrderForm()
if request.method == 'POST':
form = CreateOrderForm(request.POST, request.FILES)
if form.is_valid:
order = form.save(commit=False)
order.buyer = profile
order.save()
# form.save()
messages.info(request, 'Order Succesfully Created')
return redirect('create_order')
else:
messages.error(request, 'Order Not Created! Try Again Later')
context = {'form':form}
return render(request, 'users/create_order.html', context)
Any help will he highly appreciated.

How to create Quiz Instance from a m2m Model?

I want to create a Quiz App where user can sign in and solve the Quizes which is related to the specific Subject. And the user's data should be stored in the database. In other word, If the user solves the all questions, I have to create a Quiz Instance for him/her. Here i used M2M relationship where many user can solve one subject or one Subject can be solved by many users. When i create Quiz Instance from admin panel it is not giving me an error, But i couldn't create it from views.py. This is my Quiz Model:
from django.contrib.auth.models import User
ANSWER_CHOICES = (
("A", "A"),
("B", "B"),
("C", "C"),
("D", "D"),
)
# Create your models here.
class Subject(models.Model):
name = models.CharField(max_length=150, null=True, blank=True)
teacher = models.CharField(max_length=200, null=True, blank=True)
description = models.CharField(max_length=250, null=True, blank=True)
featured_image = models.ImageField(null=True, blank=True, default='default.jpg')
created = models.DateTimeField(auto_now_add=True)
def __str__(self) -> str:
return str(self.name)
class Meta:
ordering = ['id']
class Quiz(models.Model):
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, null=True, blank=True)
question = models.TextField(null=True, blank=True)
a = models.CharField(max_length=50, null=True, blank=True, unique=True)
b = models.CharField(max_length=50, null=True, blank=True, unique=True)
c = models.CharField(max_length=50, null=True, blank=True, unique=True)
d = models.CharField(max_length=50, null=True, blank=True, unique=True)
options = models.CharField(max_length=50, choices=ANSWER_CHOICES, blank=True, null=True, default='A')
answer = models.CharField(max_length=50, blank=True, null=True)
submitted = models.BooleanField(default=False)
def __str__(self) -> str:
return str(self.question)
class Meta:
ordering = ['question']
class QuizInstance(models.Model):
username = models.CharField(max_length=200, null=True, blank=True)
taker = models.ManyToManyField(User)
quiz = models.ManyToManyField(Subject)
quiz_taken = models.DateTimeField(auto_now_add=True)
score = models.IntegerField(default=0)
complete = models.BooleanField(default=False, null=True, blank=True)
def __str__(self) -> str:
return str('Exam Test')
Also, i want to show the result of the Quiz when the quiz is completed.Therefore i created var score, but no metter what i do i couldn't implement.
my views.py model:
from django.shortcuts import render, redirect
from .models import Subject, Quiz
from django.core.paginator import Paginator
from django.http import HttpResponse
from .forms import AnswerOptionsForm
from .models import QuizInstance
from django.contrib.auth.decorators import login_required
# Create your views here.
def homePage(request):
return render(request, 'home.html')
def quizCard(request):
subjects = Subject.objects.all()
context = {'subjects': subjects}
return render(request, 'quiz-card.html', context)
#login_required(login_url='sign-in')
def getQuestion(request, id):
subject = Subject.objects.get(id=id)
form = AnswerOptionsForm()
obj = subject.quiz_set.all()
p = Paginator(obj, 1)
submitted = False
try:
page = int(request.GET.get('page', '1'))
except:
page = 1
try:
questions = p.page(page)
except(EmptyPage, InvalidPage):
return redirect('result', int(subject.id))
page = p.num_pages
if request.method == 'POST':
submitted = True
currentQuestion = Quiz.objects.get(id=page)
currentQuestion.submitted = True
ans = request.POST.get('options')
print(ans)
if currentQuestion.answer == ans:
pass
# exam.score += 1
# exam.save()
# print(exam.score)
context = {'obj': obj, 'questions': questions, 'page':page, 'form': form, 'submitted': submitted, 'subject': subject}
return render(request, 'questions.html', context)
def result(request, id):
user = request.user.useraccount
subject = Subject.objects.get(id=id)
number_of_questions = len(subject.quiz_set.all())
user.completed_subject.add(subject)
user.save()
###This is Giving me an error###
exam = QuizInstance.objects.filter(
taker = request.user,
quiz = subject,
)
return HttpResponse(f'You have found out of {number_of_questions}')
def retakeQuiz(request, id):
subject = Subject.objects.get(id=id)
exam = QuizInstance.objects.filter(
taker = request.user,
quiz = subject,
score = 0,
complete = False,
)
exam.score = 0
return redirect('question', id)
user models.py
from django.db import models
from django.contrib.auth.models import User
from quiz.models import Quiz
from quiz.models import Subject
# Create your models here.
class UserAccount(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
username = models.CharField(max_length=150, blank=True, null=True)
programming_language = models.CharField(max_length=200, blank=True, null=True)
password = models.CharField(max_length=200, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
email = models.EmailField(max_length=300, blank=True, null=True)
completed_subject = models.ManyToManyField(Subject, default=Subject.objects.all)
def __str__(self) -> str:
return str(self.username)

Foreignkey get avatar

I am learning how to build a Learning management system and I am having trouble trying to attach a users avatar to any posted comments they make.
Any direction/help would be really appreciated.
So I have a Profile model and a Comment model and I have added a Foreignkey to the Profile model in my Comment model. How can I get the users avatar from the Profile model and render this in the comments box in HTML?
Here are my models:
class Comment(models.Model):
course = models.ForeignKey(Course, related_name='comments', on_delete=models.CASCADE)
user_avatar = models.ForeignKey(Profile, null=True, related_name="comments", on_delete=models.CASCADE)
lesson = models.ForeignKey(Lesson, related_name='comments', on_delete=models.CASCADE)
name = models.CharField(max_length=100)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, related_name='comments', on_delete=models.CASCADE)
class Profile(models.Model):
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
name = models.CharField(max_length=100, blank=True, null=True)
occupation = models.CharField(max_length=100, blank=True, null=True)
residence = models.CharField(max_length=100, blank=True, null=True)
active_id = models.BooleanField(default=True)
avatar = models.ImageField(null=True, blank=True, upload_to ='uploads/profile_pics/',default='uploads/default.jpg')
and my views.py:
#api_view(['POST'])
def add_comment(request, course_slug, lesson_slug, pk):
data = request.data
name = data.get('name')
content = data.get('content')
course = Course.objects.get(slug=course_slug)
lesson = Lesson.objects.get(slug=lesson_slug)
profile = Profile.objects.get(id=pk)
comment = Comment.objects.create(course=course, lesson=lesson, name=name, content=content, user_avatar=request.profile, created_by=request.user)
serializer = CommentsSerializer(comment)
return Response(serializer.data)
serializers.py:
class CommentsSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ('id', 'name', 'content', 'created_at', 'user_avatar', 'created_by')

Cannot assign "'1'": "Groups.profile" must be a "Profile" instance

I have Profile Model that have instance model user.. I am trying to create group using form. that group model have Profile model as instance, so how do I select authenticated user automatic to create group, I getting confused...
This is my Group Model
class Groups(models.Model):
profile = models.ForeignKey(Profile, related_name='my_groups', on_delete=models.CASCADE)
groups_name = models.CharField(max_length=150)
slug = models.SlugField(max_length=150, unique=True)
cover_pic = models.ImageField(upload_to='images/groups/', null=True, blank=True)
type_group = models.CharField(max_length=150)
created_date = models.DateTimeField(auto_now_add=True)
about_group = models.TextField(max_length=600)
members = models.ManyToManyField(Profile,through="GroupMember")
def __str__(self):
return self.groups_name
This is my profile Model
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
slug = models.SlugField(max_length=100, unique=True)
profile_pic = models.ImageField(upload_to='images/user/profile/', null=True, blank=True)
cover_pic = models.ImageField(upload_to='images/user/profile/', null=True, blank=True)
user_bio = models.TextField(null=True,blank=True, max_length=255)
designation = models.CharField(blank=True,null=True, max_length=255)
education = models.CharField(blank=True, null=True, max_length=255)
marital_status = models.CharField(blank=True, null=True, max_length=60)
hobbies = models.CharField(blank=True, null=True, max_length=500)
location = models.CharField(blank=True, null=True, max_length=500)
mobile = models.IntegerField(blank=True, null=True)
def __str__(self):
return str(self.user)
This is form for create group
class GroupCreateForm(forms.ModelForm):
class Meta:
model = Groups
fields = ('cover_pic', 'profile', 'groups_name', 'type_group', 'about_group')
profile = forms.CharField(widget=forms.TextInput(attrs={
'class': 'form-control input-group-text',
'value':'',
'id':'somesh',
'type': 'hidden',
}))
This is create group html file
this is html page
this is error..
You have set a CharField for profile in your form. When you send data to this form, it tries to make a Group record with a FK to a CharField for example "1" and this gives you error because you should pass Profile object to Group.
Depends on what exactly you want, there are some options.
You can use ModelChoiceField. Read about it in https://docs.djangoproject.com/en/3.2/ref/forms/fields/#django.forms.ModelChoiceField
Or you can use Inline FormSet and read about it in https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#inline-formsets
And an example for Inline FormSet in Creating a model and related models with Inline formsets

Get user instance from profile model __str__ in django

I have this simple model:
class Profile(models.Model):
bio = models.CharField(max_length=300, blank=False)
location = models.CharField(max_length=50, blank=
edu = models.CharField(max_length=250, blank=True, null=False)
profession = models.CharField(max_length=50, blank=True)
profile_image = models.ImageField(
upload_to=upload_image, blank=True, null=False)
def __str__(self):
try:
return str(self.pk)
except:
return ""
and a User model:
class User(AbstractBaseUser, UserTimeStamp):
first_name = models.CharField(max_length=50, blank=False, null=False)
email = models.EmailField(unique=True, blank=False, null=False)
profile = models.OneToOneField(Profile, on_delete=models.CASCADE)
uuid = models.UUIDField(
db_index=True,
default=uuid_lib.uuid4,
editable=False
)
is_admin = models.BooleanField(default=False, blank=False, null=False)
is_staff = models.BooleanField(default=False, blank=False, null=False)
is_active = models.BooleanField(default=True, blank=False, null=False)
objects = UserManager()
USERNAME_FIELD = "email"
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, perm_label):
return True
As you can see in User model I have a OneToOneField to Profile.
but in Profile model I can't access user instance to just use its email in str method. something like this:
def __str__(self):
return self.user.email
How can I do this? sometime these relations are confusing to me.
UPDATED
Yes self.user.email works well. but the problem is something else.
I have two type of users. users and teachers.
and each of them has field profile in their model. so if I say:
def __str__(self):
return self.user.email
It just returns email of user instances. what about teachers?
user model:
class User(AbstractBaseUser, UserTimeStamp):
profile = models.OneToOneField(Profile, on_delete=models.CASCADE, related_name='user_profile')
teacher model:
class Teacher(AbstractBaseUser, UserTimeStamp):
profile = models.OneToOneField(Profile, on_delete=models.CASCADE, related_name='teacher_profile')
profile model:
def __str__(self):
if hasattr(self, 'user_profile'):
# profile belong to user
print(self.user_profile.pk)
elif hasattr(self, 'teacher_profile'):
# profile belong to teacher
print(self.teacher_profile.pk)

Categories

Resources