I have a model which adds(assigns) users to the academy (academy user), the issue is I am able to add the same user multiple times to the academy. What am I doing wrong here?
class AcademyPlayer(models.Model):
academy = models.ForeignKey(Academy, on_delete=models.CASCADE)
player = models.ForeignKey('player.Player', on_delete=models.CASCADE)
date_joined = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.player.user.name
I am adding the player.Player model for reference:
class Player(models.Model):
count = models.IntegerField(
_('count'),
null=True,
blank=True
)
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE, related_name='player_user')
def __str__(self):
return self.user.email
class AcademyPlayer(models.Model):
academy = models.OneToOneField(Academy, on_delete=models.CASCADE)
player = models.OneToOneField('player.Player', on_delete=models.CASCADE)
date_joined = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.player.user.name
use OneToOneField for this
and dont forget to makemigrations and migrate after this change
Related
I'm doing a cookbook app, which help users find meal thay can do with their ingridients. I'm using Django RestFramework, and i need to return list of avaliable meals that user can do, but don't know how to do search by ingridients
My models.py:
#models.py
class Meal(models.Model):
name = models.CharField(max_length=250)
description = models.TextField(blank=True, null=True)
recipe = models.TextField()
is_published = models.BooleanField(default=False)
category = ForeignKey('Category', on_delete=models.CASCADE, null=True)
user = ForeignKey(User, verbose_name='User', on_delete= models.CASCADE)
difficulty = ForeignKey('Difficulty', on_delete=models.PROTECT, null=True)
ingridients = models.ManyToManyField('Ingridient')
class Ingridient(models.Model):
name = models.CharField(max_length=100, db_index=True)
ico = models.ImageField(upload_to="photos/%Y/%m/%d/", blank=True, null=True)
category = ForeignKey('CategoryIngridients', on_delete=models.CASCADE, null=True)
def __str__(self):
return self.name
class CookBookUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
ingridients = models.ManyToManyField('Ingridient')
serializer.py
class MealSerializer(serializers.ModelSerializer):
class Meta:
model = Meal
fields = "__all__"
views.py
class CraftWithUsersIngridientsListAPIView(generics.ListAPIView):
serializer_class = MealSerializer
def get_queryset(self):
return Meal.objects.filter(ingridients=CookBookUser.objects.filter(user_id = self.request.user.id).ingridients)
CraftWithUsersIngridientsListAPIView isn't working and I get AttributeError 'QuerySet' object has no attribute 'ingridients', can someone help fix this?
I tried building different serializer but it doesn't help
class CraftWithUsersIngridientsListAPIView(generics.ListAPIView):
serializer_class = MealSerializer
def get_queryset(self):
user_ingredients = CookBookUser.objects.get(user=self.request.user).ingredients.all()
return Meal.objects.filter(ingredients__in=user_ingredients)
This way, you first get the CookBookUser instance for the current user, then get all of their ingredients, and finally, filter the Meal objects that contain those ingredients. The __in query lookup is used to check if the meal ingredients are in the user's ingredients.
I also need the field (commentGroupDesc) from the foreign keys objects.
models.py
class commentGroup (models.Model):
commentGroup = models.CharField(_("commentGroup"), primary_key=True, max_length=255)
commentGroupDesc = models.CharField(_("commentGroupDesc"),null=True, blank=True, max_length=255)
def __str__(self):
return str(self.commentGroup)
class Meta:
ordering = ['commentGroup']
class Comment (models.Model):
commentID = models.AutoField(_("commentID"),primary_key=True)
commentUser = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
commentGroup = models.ForeignKey(commentGroup, on_delete=models.CASCADE, null=True)
commentCI = models.ForeignKey(Servicenow, on_delete=models.CASCADE, null=True)
commentText = RichTextField(_("commentText"), null=True, blank=True)
commentTableUpdated = models.CharField(_("commentTableUpdated"), null=True, blank=True, max_length=25)
def __str__(self):
return str(self.commentGroup)
class Meta:
ordering = ['commentGroup']
views.py
comment = Comment.objects.get(pk=commentID)
Here I get the commentGroup fine but I also need commentGroupDesc to put into my form.
At first, it's not a good thing to name same your model field as model name which is commentGroup kindly change field name, and run migration commands.
You can simply use chaining to get commentGroupDesc, also it's better to use get_object_or_404() so:
comment = get_object_or_404(Comment,pk=commentID)
group_desc = comment.commentGroup.commentGroupDesc
Remember to change field and model name first.
Another question from me tonight and I hope I can explain it adequately:
I got three classes in my "models.py":
class Customer(models.Model):
full_name = models.CharField(max_length=100, null=True, unique=True)
short_name = models.CharField(max_length=8, null=True, unique=True)
class Project(models.Model):
customer = models.ForeignKey(Customer, null=False, on_delete=models.CASCADE)
name = models.CharField(max_length=255, null=True, unique=True)
...
class Entry(models.Model):
user = models.ForeignKey(User, null=True, blank=False, on_delete=models.CASCADE)
customer = models.ForeignKey(Customer, null=True, blank=False, on_delete=models.CASCADE)
project = models.ForeignKey(Project, null=True, blank=False, on_delete=models.CASCADE)
date = models.DateField()
shortText = models.CharField(max_length=100, null=False, blank=False)
...
Note: One Customer can have multiple Projects.
On one of my sites there's a table with buttons beside each "Customer". The plan is, that it should lead me to another page, were the user can write and save his "Entry". Right now, the PrimaryKey inside the Button/Link contains the ID of the "Customer".
My question is: is it possible to limit the choices of the "Project" (inside a Drop-Down-Menu) to the "Customer" that has been clicked on? And is creating a ModelForm the right thing to do?
Thanks to all of you and a good night!
Well, don't know if this is the right way, but I found a solution for my problem:
Wrote a "forms.ModelForm" for my view-function...
class EntryForm(ModelForm):
class Meta:
model = Entry
fields = '__all__'
def __init__(self, *args, pk, **kwargs):
super().__init__(*args, **kwargs)
self.fields['project'].queryset = Project.objects.filter(customer_id=pk)
Insert my ModelForm into the view-function...
def WriteEntry(request, pk):
form = EntryForm(pk=pk)
if request.method =='POST':
form = EntryForm(request.POST, pk)
if form.is_valid():
form.save()
...
context = {'form': form}
return render(request, '...html', context)
i'm working on a project the scenario : teachers can make course and publish it in Course model and also institute can make course in Course model?
how can i make it automatically choose one of the foreign key fields?
both institutes and teacher can have post
class Institute(models.Model):
courses = GenericRelation(Course)
institute_name = models.OneToOneField(CustomUser,on_delete=models.CASCADE)
institute_id = models.SlugField(unique=True,default=slug_generator(),blank=True)
phone_number = models.CharField(max_length=11)
locations = models.OneToOneField(Location,on_delete=models.DO_NOTHING,default='')
institute_name.is_institute = True
pass...
def __str__(self):
return self.institute_name.username
class Teacher(models.Model):
course = GenericRelation(Course)
teacher = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
teacher_slug = models.SlugField(unique=True,default=slug_generator())
phone_number = models.CharField(max_length=11,default='')
teacher.is_teacher = True
certification = models.ForeignKey(Certification,on_delete=models.CASCADE, blank=True,null=True)
def __str__(self):
return self.teacher.username
class CustomUser(AbstractUser):
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
is_institute = models.BooleanField(default=False)
email = models.EmailField(unique=True)
objects = UserManager()
def __str__(self):
return self.username
class Student(models.Model):
student = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
student.is_student = True
student_slug = models.SlugField(unique=True,default=slug_generator())
def __str__(self):
return self.student.username
Then define:
if user loggedin in user.is_institute
So querying in institute model
else loggedin in user.is_teacher
And then will work on teacher model.
Does this structure fine ?
I've heard that generic foreign keys not working with API
i also tried this , but i dont how to query them
class Course(models.Model):
course_name = models.CharField(max_length=20)
tags = models.ManyToManyField(Category)
time_created = models.DateTimeField(auto_now_add=True)
content_type = models.ForeignKey(ContentType , on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type','object_id')
def __str__(self):
return self.course_name
from django.contrib.contenttypes.models import ContentType
Teacher ,Institute have different fields name
Thanks
I don't think that GenericRelation is something you really need for this.
How about change the structure a little bit. Let's have Course as the main model for the task.
For example
class Course(models.Model):
teacher = models.ForeignKey(Teacher, related_name='courses', on_delete=models.CASCADE, null=True, blank=True)
institute = models.ForeignKey(Institute, related_name='courses', on_delete=models.CASCADE, null=True, blank=True)
# other necessary fields
#property
def is_teacher(self):
return self.teacher is not None
#property
def is_institute(self):
return self.institute is not None
After that you can check if Course is made by institute like
if course_object.is_teacher:
But if you really want to differentiate your users by institute or teacher you'd need to make custom user model, here's the starting point for you https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project
In that case in your Course model you'd have only one field something like author = models.ForeignKey(User, related_name='courses', on_delete=models.CASCADE)
Hope I've got your question right.
I want to have a form which only offers the user to post a question for a project he is participating in.
models.py:
class Project(models.Model):
project_name = models.CharField(max_length=255, unique=True, blank=False)
def __str__(self):
return str(self.project_name)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
project = models.ManyToManyField(Project)
def __str__(self):
return str(self.user)
class Question(models.Model):
title = models.CharField(max_length=255, blank=False)
content = tinymce_models.HTMLField(blank=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
...
def __str__(self):
return str(self.title)
class QuestionForm(ModelForm):
class Meta:
model = Question
fields = ['title', 'content', 'project']
in views.py:
form = QuestionForm()
form.fields["project"].queryset = Project.objects.filter(project_name__in=request.user.profile.project.all())
But somehow the result of the query always stays empty.
Does somebody maybe have an idea what I am missing?
Your query is over complicated. You should just use the user's projects directly:
form.fields["project"].queryset = request.user.profile.project.all())