Cannot resolve keyword 'is_staff' into field. Choices are: dob, experience, id,user, user_id
I get the above error when adding trainer as a Foreign Key to the Subscription model and then accessing any record for Subscription model from admin panel
class Subscription(models.Model):
client = models.OneToOneField(ClientProfile, on_delete=models.CASCADE)
trainer = models.ForeignKey(TrainerProfile, null=True, blank=True,
on_delete=models.SET_NULL, limit_choices_to={'is_staff': True})
plan = models.ForeignKey(Plan, on_delete=models.CASCADE)
transaction = models.OneToOneField(PaymentHistory, on_delete=models.CASCADE)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
class TrainerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
dob = models.DateField(null=True)
experience = models.PositiveIntegerField(default=0)
You're trying to access an attribute is_staff, which does not exist on the TrainerProfile model. is_staff is an attribute of User, which you reference in your TrainerProfile model's user field.
In order to access this property, you need to "traverse" the relationship from Subscription -> TrainerProfile -> User. Django allows you to do this by using double-underscore notation, like this: some_fk_field__fk_field_attribute.
In your example, you need to change your limit_choices_to option on trainer to traverse the relationship to the user, like so:
class Subscription(models.Model):
client = models.OneToOneField(ClientProfile, on_delete=models.CASCADE)
trainer = models.ForeignKey(TrainerProfile, null=True, blank=True,
on_delete=models.SET_NULL, limit_choices_to={'user__is_staff': True})
plan = models.ForeignKey(Plan, on_delete=models.CASCADE)
transaction = models.OneToOneField(PaymentHistory, on_delete=models.CASCADE)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
class TrainerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
dob = models.DateField(null=True)
experience = models.PositiveIntegerField(default=0)
You are referencing the nested relationship in wrong way
class Subscription(models.Model):
# other fields
trainer = models.ForeignKey(TrainerProfile, null=True, blank=True,
on_delete=models.SET_NULL,
limit_choices_to={'user__is_staff': True})
That is, it should be user__is_staff instead of is_staff
Related
i'm new with Django and as I read the code, I don't understand the message_set attribute of Django model(called Room):
def room(request, pk):
room = Room.objects.get(id=pk)
**room_messages = room.message_set.all()**
participants = room.participants.all()
portion of Models:
class Room(models.Model):
host = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
topic = models.ForeignKey(Topic, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
participants = models.ManyToManyField(
User, related_name='participants', blank=True)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
class Message(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
room = models.ForeignKey(Room, on_delete=models.CASCADE)
body = models.TextField()
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
If you define a ForeignKey from Message to Room, Django will add a relation in reverse to the from the Room model to its related Messages. By default this relation is named modelname_set with modelname the name of the origin of the model. You can specify another name by overriding the related_name=… parameter [Django-doc].
If you thus access the relation in reverse, you get all Message objects with room as there room, an equivalent query to room.message_set.all() is thus Message.objects.filter(room=room).
I need to log the transaction of the item movement in a warehouse. I've 3 tables as shown in the below image. However Django response error:
ERRORS:
chemstore.ItemTransaction: (models.E007) Field 'outbin' has column name 'bin_code_id' that is used by another field.
which is complaining of multiple uses of the same foreign key. Is my table design problem? or is it not allowed under Django? How can I achieve this under Django? thankyou
DB design
[Models]
class BinLocation(models.Model):
bin_code = models.CharField(max_length=10, unique=True)
desc = models.CharField(max_length=50)
def __str__(self):
return f"{self.bin_code}"
class Meta:
indexes = [models.Index(fields=['bin_code'])]
class ItemMaster(models.Model):
item_code = models.CharField(max_length=20, unique=True)
desc = models.CharField(max_length=50)
long_desc = models.CharField(max_length=150, blank=True)
helper_qty = models.DecimalField(max_digits=10, decimal_places=4)
unit = models.CharField(max_length=10, blank=False)
def __str__(self):
return f"{self.item_code}"
class Meta:
verbose_name = "Item"
verbose_name_plural = "Items"
indexes = [models.Index(fields=['item_code'])]
class ItemTransaction(models.Model):
trace_code = models.CharField(max_length=20, unique=False)
item_code = models.ForeignKey(
ItemMaster, related_name='trans', on_delete=models.CASCADE, null=False)
datetime = models.DateTimeField(auto_now=False, auto_now_add=False)
qty = models.DecimalField(max_digits=10, decimal_places=4)
unit = models.CharField(max_length=10, blank=False)
action = models.CharField(
max_length=1, choices=ACTION, blank=False, null=False)
in_bin = models.ForeignKey(
BinLocation, related_name='in_logs', db_column='bin_code_id', on_delete=models.CASCADE, null=False)
out_bin = models.ForeignKey(
BinLocation, related_name='out_logs', db_column='bin_code_id', on_delete=models.CASCADE, null=False)
remarks = models.TextField(blank=True)
def __str__(self):
return f"{self.trace_code} {self.datetime} {self.item_code} {dict(ACTION)[self.action]} {self.qty} {self.unit} {self.in_bin} {self.out_bin}"
you have same db_column in two fields so change it
in_bin = models.ForeignKey(
BinLocation, related_name='in_logs', db_column='bin_code_id', on_delete=models.CASCADE, null=False)
out_bin = models.ForeignKey(
BinLocation, related_name='out_logs', db_column='other_bin_code', on_delete=models.CASCADE, null=False) /*change db_column whatever you want but it should be unique*/
If are linked to the same model name, You should use different related_name for each foreign_key filed . here is the exemple :
address1 = models.ForeignKey(Address, verbose_name=_("Address1"),related_name="Address1", null=True, blank=True,on_delete=models.SET_NULL)
address2 = models.ForeignKey(Address, verbose_name=_("Address2"),related_name="Address2", null=True, blank=True,on_delete=models.SET_NULL)
thank you for everyone helped. According to Aleksei and Tabaane, it is my DB design issue (broken the RDBMS rule) rather than Django issue. I searched online and find something similar: ONE-TO-MANY DB design pattern
In my case, I should store in bin and out bin as separated transaction instead of both in and out in a single transaction. This is my solution. thankyou.
p.s. alternative solution: I keep in bin and out bin as single transaction, but I don't use foreign key for bins, query both in bin and out bin for the bin selection by client application.
I have the following model in Django
class Transfer(models.Model):
user = models.ForeignKey(User, on_delete=models.PROTECT, limit_choices_to={'is_accepted':True})
amount = models.IntegerField(default=0)
transfer_date = models.DateTimeField(default=timezone.now)
company = models.ForeignKey(Company, on_delete=models.PROTECT)
I would like to filter the users based on is_accepted field. The problem is, that this field is declared in a model called Employee, which is in onetoone relationship with user.
Is there any possibility to reach Employee fields and filter them in this manner?
You can normally define a filter like:
class Transfer(models.Model):
user = models.ForeignKey(
User,
on_delete=models.PROTECT,
limit_choices_to={'employee__is_accepted': True}
)
amount = models.IntegerField(default=0)
transfer_date = models.DateTimeField(default=timezone.now)
company = models.ForeignKey(Company, on_delete=models.PROTECT)
So basically i have to make sure Users that are from the same department field to view and create any datas in the database. Not sure how to apply it using field-based user permissions?
class Profile(AbstractUser):
class Meta:
verbose_name_plural = 'Profiles'
company = models.CharField(max_length=30, null=True)
contact = models.CharField(max_length=20, null=True)
branch = models.ForeignKey('generals.Branch',
on_delete=models.CASCADE)
department = models.ForeignKey('generals.Department',
on_delete=models.CASCADE)
created_by = models.CharField(max_length=20)
modify_by = models.CharField(max_length=20)
modify_date = models.DateTimeField(default=datetime.now, blank=True)
is_active = models.BooleanField(default=False, null=True,
blank=True)
is_superuser = models.BooleanField(default=False, null=True,
blank=True)
is_staff = models.BooleanField(default=False, null=True,
blank=True)
def __str__(self):
return self.username
You should use what's already implemented in Django, and you'll gain a lot of time.
class Person(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
company = models.ForeignKey(Group, on_delete=models.CASCADE)
contact = models.ForeignKey('Person', on_delete=models.CASCADE)
branch = models.ForeignKey('generals.Branch',
on_delete=models.CASCADE)
department = models.ForeignKey('generals.Department',
on_delete=models.CASCADE)
created_by = models.ForeignKey('Person', on_delete=models.CASCADE)
modify_by = models.ForeignKey('Person', on_delete=models.CASCADE)
modify_date = models.DateTimeField(default=datetime.now, blank=True)
even though my eyes are burning because my syntax here is not PEP8 compliant, you should get the big picture: all the permissions are already handled by User and Group.
Just create a Group that has the name of the company, and give this group access (or not) to specific tables.
What I'd like to be able to do is similar to this pseudo-code - I'm just completely unaware of how to do this in python:
user_groups = request.user.participant_groups.all()
if group in user_groups not in self.object.settings.groups.all():
Basically, I'd like to check if any of the objects in user_groups are in self.object.settings.groups.all(). Is there a simple way to do this?
Models:
class Group(models.Model):
participants = models.ManyToManyField('auth.User', null=True, blank=True, related_name='participant_groups')
title = models.CharField(max_length=180)
date = models.DateTimeField(null=True, blank=True, editable=False)
modified = models.DateTimeField(null=True, blank=True, editable=False)
class Settings(models.Model):
user = models.ForeignKey('auth.User', related_name='settings_objects')
groups = models.ManyToManyField('groups.Group', null=True, blank=True)
participants = models.ManyToManyField('auth.User', null=True, blank=True, related_name='accessible_objects')
private = models.BooleanField(default=True)
What I'm trying to do is check if any of a user's participant_groups (reverse relation to user on group model) are in a settings objects groups manytomany relation.
Try this -
common_groups = user.participant_groups.annotate(
num_settings=Count('settings_objects')
).filter(num_settings__gt=0)
# You can get a count like this
count_of_above = common_groups.count()
I'm assuming self.object.settings is an instance of Settings for the current user. You should make it clear.