I am trying to assign value to a database entry that is defined using the models.ForeignKey. How should I refer to the variables in the referred model?
In the code below, the assignment update_user.appointments.requester_name = requesting_user does not work. Googling has not helped me find the right solution. How should one refer to such variables from django/python?
Below is my models.py
class AppointmentRequest(models.Model):
my_name = models.TextField(default='')
requester_name = models.TextField(default='')
meeting_year = models.TextField(default='')
class CustomUser(AbstractUser):
firstname = models.TextField(default='')
lastname = models.TextField(default='')
appointments = models.ForeignKey(AppointmentRequest, on_delete=models.CASCADE, default='', blank=True, null=True)
I want to modify the value of appointments entry, i.e., my_name, requester_name, etc.
Below is the code in views.py
def book_appointment(request):
requesting_user = request.GET['requesting_user']
update_user = CustomUser.objects.get(username=requested_user)
update_user.appointments.requester_name = requesting_user
The reason you're probably getting the "NoneType" object has not attribute "requester_name" is that update_user.appointments is probably null
appointments = models.ForeignKey(AppointmentRequest, on_delete=models.CASCADE, default='', blank=True, null=True)
That says your ForeignKey can be null, so that's what it's probably returning to you.
What you should really do is:
if update_user.appointments:
update_user.appointments.requester_name = request.GET['requesting_user']
else:
apt_request = AppointmentRequest()
apt_request.requester_name = request.GET['requesting_user']
apt_request.save()
update_user.appointments = apt_request()
update_user.save()
This creates an AppointmentRequest object that you use to set the appointments ForeignKey IF update_user.appointments is null.
ALSO, in this code:
appointments = models.ForeignKey(AppointmentRequest, on_delete=models.CASCADE, default='', blank=True, null=True)
I'm pretty sure default='' does nothing and it defaults to null. So you can omit that part of the code.
Cont in comments...:
Oh. Another thing. I wouldn't use ForeignKeys for this. I would Use ManyToMany unless the user is only allowed ONE appointment ever.
requesting_user = request.GET['requesting_user']
in this part you are getting the user as json not a django model instance, so when you apply
update_user = CustomUser.objects.get(username=requested_user)
it doesn't get any thing.
you should use django serializer to make a userSerializer then use it to convert the json user to model instance then when you apply
update_user = CustomUser.objects.get(username=requested_user)
this should work.
Related
well my college is making us go learn a framework and make a website with it in a month, and it's really killing me, because of that I couldn't really get a good understanding of the Django framework as I am making progress while watching YouTube vids and reading docs.
Anyways my models are all messed up which made the job even harder, and whenever I solve a problem another one arises, but the deadline is close and making any changes to the models will cost me a great deal of time. This time my problem is about fetching data.
The concerned models are the following:
The User class for authentication
class User(AbstractBaseUser, PermissionsMixin):
id = models.AutoField(primary_key=True,null=False)
username = models.CharField(max_length=50)
email = models.EmailField(unique=True)
nom = models.CharField(max_length=255)
prenom = models.CharField(max_length=255)
usertype = models.CharField(choices=types,max_length=20,default="user")
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now=True)
is_superuser = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
student_data = models.OneToOneField(Etudiant, on_delete=models.CASCADE,blank=True, null=True,related_name='Etudiant_access')
Prof_data = models.OneToOneField(Prof, on_delete=models.CASCADE,blank=True, null=True)
objects=UserManager()
def __str__(self):
return self.prenom + " " + self.nom
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
The Students(Etudiant) class for managing the students:
class Etudiant(models.Model):
filiere = models.ForeignKey(Filiere, on_delete=models.DO_NOTHING)
classe = models.ForeignKey(Classe,null=True, on_delete=models.DO_NOTHING)
notes = models.ManyToManyField(note,blank=True, null=True)
The class Classe (LMAO) for managing the different classes:
class Classe(models.Model):
#Cla_id = models.AutoField(primary_key=True, null=False)
Designation = models.CharField(max_length=100)
filiere = models.ForeignKey(Filiere, on_delete=models.CASCADE)
Epreuve = models.ManyToManyField(Epreuve,blank=True, null=True)
def __str__(self):
return self.Designation
The thing is that I wanna fetch all data of the Users that are students (which means that their Prof_data attribute is blank/null and their student_data attribute is pointing to the Etudiant(Student) class while having an Etudiant.classe attribute equals to a value in the view's parameters
I've solved a great deal of it but I'm stuck at the end
This is my view function:
#login_required
def class_info(request,design):
#getting the Classe(s) from the url which Designation == design
classe_now = Classe.objects.get(Designation=design)
print(classe_now) # This works like a charm
#getting the Students objects that are part of the class_now
Etudiants = Etudiant.objects.filter(classe=classe_now)
print(Etudiants) # This works too. It returns the 'Etudiant' objects from where i wanna access to the Users data
#getting the User data of the student objects (This is where i get confused)
students_to_show = User.objects.filter(student_data=Etudiants)
pprint(students_to_show)
return render(request, 'Prof/class_info.html')
I am really confused, you are truly my last hope in this, and thank you for your time.
You can filter your User model by selecting all users that do have empty/null relation to Prof model and nonempty/null relation to Etudiant model.
student_users = User.objects.filter(Prof_data__isnull=True, student_data__isnull=False)
then for each stident_user, you can fetch its student data in the following manner:
student_user = student_users[0]
student_user.student_data.filiere
student_user.student_data.classe
student_user.student_data.notes
You can then pass the queryset result to the render function as a context variable. Check this brief tutorial on how to pass data to templates.
I have two django models:
class Order(models.Model):
date = models.DateTimeField()
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='orders')
shipping_address = models.CharField(max_length=200)
phone_number = models.CharField(max_length=9)
comment = models.CharField(max_length=100, blank=True, null=True)
class OrderStatus(models.Model):
STATUS_ACCEPTED = 1
STATUS_PROCESSING = 2
STATUS_DELIVERING = 3
STATUS_COMPLETED = 4
CODE_CHOICES = (
(STATUS_ACCEPTED, 'accepted'),
(STATUS_PROCESSING, 'processing'),
(STATUS_DELIVERING, 'delivering'),
(STATUS_COMPLETED, 'completed'),
)
date_created = models.DateTimeField(auto_now_add=True)
code = models.PositiveSmallIntegerField(choices=CODE_CHOICES)
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='status_list')
Normally if I wanted to get all the orders with 'accepted' status I could write Order.objects.filter(orderstatus__code=1).
But how can I make django admin to create OrderStatus list filter?
I have googled a lot and found only one answer here on stackoverflow, which claims simply adding reverse model ('orderstatus' in my case) to list_filter tuple should work, but I get an error message: The value of 'list_filter[1]' refers to 'orderstatus', which does not refer to a Field.
What am I doing wrong?
Did you try by you self before posting question here, because there are lots of question related to this one, Any way i think this link will help you.
https://books.agiliq.com/projects/django-admin-cookbook/en/latest/many_to_many.html
The value of 'list_filter[1]' refers to 'orderstatus', which does not refer to a Field.
This is because orderstatus is not a field in your model. Either change order field to orderstatus or change the name passed to list_filter to the name of your field.
I'm working in Django 2.0
I have a model Note to save note and two another models to add color labels to the note.
class Note(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=250, blank=True, default='Untitled')
content = models.TextField(blank=True)
class ColorLabels(models.Model):
title = models.CharField(max_length=100, unique=True)
value = models.CharField(max_length=100)
default = models.BooleanField(default=False)
class NoteLabel(models.Model):
note = models.OneToOneField(Note, on_delete=models.CASCADE)
color_label = models.OneToOneField(ColorLabels, on_delete=models.CASCADE)
with the object of Note
note = Note.objects.get(pk=1)
I want to access associated ColorLabels's title and value fields or the NoteLabel object.
since they are one to one field. I tried doing
note.note_label
note.NoteLabel
note.note_label_set
But all returns error as
AttributeError: 'Note' object has no attribute 'note_label_set'
Unless you define related_name in your OneToOneField, Django will use lowercased model name to access related object. So, note.notelabel should work.
I'm working to remove an existing GenericForeignKey relationship from some models. Id like to change it to the Reformatted Model below. Does migrations provide a way to convert the existing content_type and object_ids to the respective new ForeignKey's? (to keep existing data). Basically brand new at programming, so pardon me if I'm asking a stupid question.
class Donation(models.Model):
amount_id = models.CharField(max_length=12, unique=True, editable=False)
date_issued=models.DateField(auto_now_add=True)
description=models.TextField(blank=True, null=True)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type','object_id')
class Individual(BaseModel):
first_name = models.CharField(max_length=50)
middle_name = models.CharField(max_length=50, blank=True,
null=True)
last_name = models.CharField(max_length=50)
suffix = models.CharField(max_length=50, blank=True, null=True)
contributor = generic.GenericRelation(Donation, related_query_name='individual')
class Organization(models.Model):
name = models.CharField(max_length=100)
contributor = generic.GenericRelation(Donation, related_query_name='organization')
Reformatted Model
class Donation(models.Model):
amount_id = models.CharField(max_length=12, unique=True, editable=False)
date_issued=models.DateField(auto_now_add=True)
description=models.TextField(blank=True, null=True)
contributor_group = models.ForeignKey(Organization, null=True, blank=True, on_delete=models.CASCADE)
contributor_individual = models.ForeignKey(Individual, null=True, blank=True, on_delete=models
Based on your model definition of Donation Model, one of fields contributor_group , contributor_model will always be Null post migration.
I hope you have taken that into you consideration.
Just to be safe Do this in two phases.
1. Keep the content_type and object_id and add the two new fields.
2. Next step remove the generic fields post data population.
There are two ways to populate those new fields
Django migrations provides you a way to populate new fields with values during the migrations. You can look it up. I haven't done that before either.
For more control and some learning as well. You can populate that via scripting as well. You can setup django-extensions module in your project. And write a script to do that population for you as well. A sample script would look like.
from myproject.models import Donation, Individual, Organization
from django.contrib.contenttypes.models import ContentType
def run():
organization_content_type = ContentType.objects.get_for_model(Organization)
individual_content_type = ContentType.obejcts.get_for_model(Individual)
donations = Donation.objects.all()
for donation in donations:
if donation.content_type_id == organization_content_type.id:
donation.contributor_group = donation.object_id
elif donation.content_type_id == individual_content_type.id:
donation.contributor_individual = donation.object_id
else:
print "Can't identify content type for donation id {}".format(donation.id)
donation.save()
Check the values are correct and then remove the generic fields.
Facing some issues with formatting here.
I want to find the number of articles for which a specific user has created articlehistory records.
The models for that look like this:
class Article(models.Model):
"""The basic entity of this app.)"""
documentID = models.CharField(blank=True, max_length=1000)
cowcode = models.IntegerField(blank=True, null=True)
pubdate = models.DateField(default=datetime.datetime.today)
headline = models.CharField(blank=True, max_length=1500)
source = models.CharField(blank=True, max_length=5000)
text = models.TextField(blank=True, max_length=1000000)
assignments = models.ManyToManyField(Assignment)
class Meta:
ordering = ['pubdate']
def __unicode__(self):
return self.headline
class ArticleHistory(models.Model):
"""(Modelname description)"""
article = models.ForeignKey(Article, related_name='Article History')
coder = models.ForeignKey(User, related_name='Article History')
last_updated = models.DateTimeField(default=datetime.datetime.now)
def __unicode__(self):
return self.last_updated
The way I'm trying to do this at the moment is like this:
assignment.finished_articles = Article.objects.filter(cowcode=country).filter(pubdate__range=(start_date,end_date), articlehistory__coder=request.user.id).count()
This doesn't work, however and exhibits another weird behaviour:
I try to do this:
for assignment in assignments:
country = assignment.country.cowcode
start_date = assignment.start_date
end_date = assignment.end_date
articles = Article.objects.filter(cowcode=country).filter(pubdate__range=(start_date,end_date)).select_related()
assignment.article_num = articles.count()
#assignment.finished_articles = Article.objects.filter(cowcode=country).filter(pubdate__range=(start_date,end_date), articlehistory__coder=request.user.id).count()
This works fine, unless I try to include finished_articles, then article_num gets shortened to one result.
It would be really great if anyone has a pointer to who to solve this.
Make use of reverse relation of ForeignKey created by parameter related_name:
Rename attribute related name to "article_history_set".
Now, it gives you easy pointer: user.article_history_set is a set of Article History objects where coder is set to this user.
Then you can find which article it is related to by doing article_history.article.
At the end, you have to get rid of repetition and get length of that list.
Here you have more about related_name attribute: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey.related_name