Django ManyToMany Relationship can't access fields - python

I have a list model that uses User as foreign key twice.
The 1st is as ForeignKey to the creator. And 2nd as ManyToManyField for users for that list
class TodoList(models.Model):
creator = models.ForeignKey(User, default=1,related_name='created_by')
list_users = models.ManyToManyField(User,related_name='list_users')
title = models.CharField(max_length=120)
slug = models.SlugField(max_length=10, blank=True, null=True)
status = models.SlugField(choices=STATUS_CHOICES, default='active', max_length=10)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
What I want to do is:
Get the users for the list.
Get the list for the logged in user.
Here is my code for #1:
todolist = get_object_or_404(TodoList, slug=list_slug)
users = todolist.list_users
The first line works fine. But when I get the list_users it will return auth.User.None even though the list has 3 users added to it through admin.
Here is my code for #2:
user = request.user
user_todo_lists = user.todolist.all()
The page will send an:
AttributeError: 'User' object has no attribute 'todolist'
but when I rename the list_users to user. It will work just fine. What could be the problem?

Regarding your first problem, you probably want todolist.list_users.all(). (That is, you want a QuerySet, not a Manager.)
Regarding your second problem, I'm not sure which relation you're actually trying to get at, but in either case you need to use the attribute defined by related_name. (That is, user.created_by.all() or user.list_users.all().)

Related

Django is rendering an awkward result

Basically, I am working on a django project, and whenever I insert data into the database, the result is weirdly formatted.
this is my model
customer.py
class Customer(models.Model):
user = models.OneToOneField(User,null=True,blank=True,on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
email= models.CharField(max_length=200, null=True)
phone_number= models.CharField(max_length=200, null=True)
def __str__(self):
return self.name
Now, say I have saved a new customer
new_customer = Customer.objects.create(name="Henry",email="henry#mail.com",phone_number="+330145786259")
new_customer.save()
when i try to retrieve the customer name i get this:
print(new_customer.name)
>('henry',)
Anyone has any insight for me???
I tried to recreate the model on a new project but still having the same result
In your customer class, you have defined a 1:1 relationship with the in-built user model class of django. And when you are creating the customer object, new_customer, you have not specified the 'user' attribute; hence, your customer object is missing a key element.
The user object already has an in-built field for storing names. It is 'first_name' and 'last_name.' You need to create a user model first before being able to create your 'Customer' model.
Your models.py should look something like this:
from django.contrib.auth.models import User
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
phone_number= models.CharField(max_length=200, null=True)
def __str__(self):
return self.user.first_name
# to return email -> self.user.email
Now to create a 'Customer' object in view.py:
from django.contrib.auth.models import User
from .models import Customer
# create a user object
myuser = User.objects.create_user(username='john', email='jlennon#beatles.com', password='glass onion')
# pass the user object to the customer model
mycustomer = Customer.objects.create(user=myuser, phone_number=123456789)
# save the customer object
mycustomer.save()
Explore django ModelForms to define the user model as per your specifications, e.g, if you don't require your users to have passwords associated with them, etc.
After much testing, I realized why I was getting the weird output.
I was directly passing data from a form to the object creation method, like so:
data = json.loads(request.body)
new_customer = Customer.objects.create(name=data['name'],email="henry#mail.com",phone_number="+330145786259")
new_customer.save()
So assigning the received data to a variable before passing it to the object creation method seems to be the right way of doing things... At least, it is working for me.

How do I limit a django model's field choices using one of the previous fields?

The following is in my models.py:
class SensorType(models.Model):
hardware_type = models.CharField(max_length=100)
is_static = models.BooleanField(default=False)
# Some other fields
class Sensor(models.Model):
device_id = models.CharField(max_length=100, primary_key=True)
sensor_type = models.ForeignKey(SensorType, on_delete=models.PROTECT)
# Some other fields
class Asset(models.Model):
name = models.CharField(max_length=100)
sensor_type = models.ForeignKey(SensorType, on_delete=models.PROTECT) # I need to use this field to filter below
sensor = models.ForeignKey(Sensor, on_delete=models.PROTECT, limit_choices_to={'sensor_type': WHAT DO I PUT HERE?},)
# Some other fields
I need to limit the choices in the sensor field of asset so that only sensors with the sensor_type set in the field immediately above, show up.
The reasoning behind this is that there will eventually be many sensors and it would be very useful to filter this. Initially I only need this to work from the admin page but this will eventually extend when I make my Create and Update Views.
Is this even possible? I'm essentially trying to access attributes before the object has actually been created.
After reading several other questions such as this one I have also looked into ModelChoiceField but the same issue exists of trying to access the form data before it has been submitted.
I'm very open to changing the model structure if that is what is required.

Delete 2 model different objects which reference each other as foreign keys

We have two Django models:
class Project(models.Model):
project_title = models.CharField(max_length=30)
owner = models.ForeignKey(User, null=True, on_delete=models.DO_NOTHING)
class User(models.Model):
usernmae = models.CharField(max_length=50)
active_project = models.ForeignKey(User, null=True, on_delete=models.DO_NOTHING, related_name='current_project')
I have a user with object (with id say 692). And this user created a project with id=12345, therefore these owner field will get have this particular referenced.
I want to delete that user. But it shows error that
delete on table "app_user" violates foreign key constraint
This is expected as on_delete=models.DO_NOTHING, was set. One way I found out was using on_delete=models.CASCADE.
Question: How should I go about deleting the user (692) without changing the model definition(having to re-run migration)?
Doing it manually by deleting the project first, leads to the same foreign-key error, as owner field is User object.
How to handle this mutual foreign key relationship while deleting, as deleting any one of those two throws the foreign-key exception?
Update
Some correction in the model definition username is the field name instead of usernmae (typo). And the foreignkey for project is Project not the User model.
class Project(models.Model):
project_title = models.CharField(max_length=30)
owner = models.ForeignKey(User, null=True, on_delete=models.DO_NOTHING)
class User(models.Model):
username = models.CharField(max_length=50)
active_project = models.ForeignKey(Project, null=True, on_delete=models.DO_NOTHING, related_name='current_project')
IF you really don't want to make a migration (any specific reason?) and if you are ok with doing this manually this time. Then you have two options:
Go into the admin panel and manually change the User field in the project instance to a different user or to NULL. Now you should be able to delete the User instance since it's not referred anymore into the project.
If that worked, you can then delete the project instane as well.
Curios if this will work, let me know!

How to insert data into a relational one to one table in django?

I have a UserProfile table which is in relation with the default Django User table. Here's how it looks.
class UserProfile(models.Model):
user = user.OneToOneField(User, on_delete=models.CASCADE)
section = models.CharField(max_length=255, blank=True)
year = models.IntegerField(null=True, blank=True)
course = models.CharField(max_length=255, blank=True)
qrcode = models.CharField(max_length=255, blank=True)
present = models.BooleanField(default=False)
I am trying to insert the data into the UserProfile table using the Django Shell.
from users.models import UserProfile
a = UserProfile(qrcode="hello")
a.save()
This is how I have always known to insert data into tables, it has always worked. BUT when i try to do this in UserProfile model. I get this exception. NOT NULL constraint failed: users_userprofile.user_id. Which in turn is caused by the following exception Error in formatting: RelatedObjectDoesNotExist: UserProfile has no user.
I somewhat understand that I somehow need to supply a user instance. But I am clueless as to how. Can someone please help me.
Firstly you need to create User.
u1 = User(username='user1')
u1.save()
Create a UserProfile. Pass the ID of the “parent” object as this object’s ID:
v1 = UserProfile(user=u1, ....)
v1.save()
refer this
You need to create your User first
user = User.objects.create(username='user')
and then you can do:
user_profile = UserProfile.objects.create(user=user, ...)

How to get data from ManyToManyField - Django

I have a problem with retrieving data from this ManyToManyField (users) of a model Event:
class Event(models.Model):
name = models.CharField(max_length=26)
description = models.CharField(max_length=200)
date = models.DateField()
user = models.ForeignKey(User)
users = models.ManyToManyField(User, related_name="users", blank=True)
image = models.ImageField(
upload_to='images/',
default='images/default.png'
)
users = models.ManyToManyField creates an additional table "events_event_users", It stores user_id and event_id fields. So I want to output all event information from Event model, where user_id from that additional table is equal to request.user. Please help, how should I do this?
You can do request.user.users.all()
Note, this is unnecessarily confusing because of the related_name you've set, which defines the backwards relation from User to Event. Leave that out, and the code is more comprehensible:
request.user.event_set.all()
(If you must set one, at least call it events, not users.)

Categories